diff --git a/src/Service.Tests/SqlTests/RestApiTests/Delete/DeleteApiTestBase.cs b/src/Service.Tests/SqlTests/RestApiTests/Delete/DeleteApiTestBase.cs
index f03b519689..87cffa252c 100644
--- a/src/Service.Tests/SqlTests/RestApiTests/Delete/DeleteApiTestBase.cs
+++ b/src/Service.Tests/SqlTests/RestApiTests/Delete/DeleteApiTestBase.cs
@@ -159,6 +159,27 @@ await SetupAndRunRestApiTest(
);
}
+ ///
+ /// Tests that a cast failure of primary key value type results in HTTP 400 Bad Request.
+ /// e.g. Attempt to cast a string '{}' to the 'id' column type of int will fail.
+ ///
+ [TestMethod]
+ public async Task DeleteWithUncastablePKValue()
+ {
+ await SetupAndRunRestApiTest(
+ primaryKeyRoute: "id/{}",
+ queryString: string.Empty,
+ entityNameOrPath: _integrationEntityName,
+ sqlQuery: string.Empty,
+ operationType: Operation.Delete,
+ requestBody: string.Empty,
+ exceptionExpected: true,
+ expectedErrorMessage: "Parameter \"{}\" cannot be resolved as column \"id\" with type \"Int32\".",
+ expectedStatusCode: HttpStatusCode.BadRequest,
+ expectedSubStatusCode: DataApiBuilderException.SubStatusCodes.BadRequest.ToString()
+ );
+ }
+
///
/// DeleteWithSqlInjectionTest attempts to inject a SQL statement
/// through the primary key route of a delete operation.
diff --git a/src/Service.Tests/SqlTests/RestApiTests/Find/FindApiTestBase.cs b/src/Service.Tests/SqlTests/RestApiTests/Find/FindApiTestBase.cs
index 51efef72d7..d4cbbe3cbe 100644
--- a/src/Service.Tests/SqlTests/RestApiTests/Find/FindApiTestBase.cs
+++ b/src/Service.Tests/SqlTests/RestApiTests/Find/FindApiTestBase.cs
@@ -1451,6 +1451,24 @@ await SetupAndRunRestApiTest(
);
}
+ ///
+ /// Tests that a cast failure of primary key value type results in HTTP 400 Bad Request.
+ /// e.g. Attempt to cast a string '{}' to the 'id' column type of int will fail.
+ ///
+ [TestMethod]
+ public async Task FindWithUncastablePKValue()
+ {
+ await SetupAndRunRestApiTest(
+ primaryKeyRoute: "id/{}",
+ queryString: string.Empty,
+ entityNameOrPath: _integrationEntityName,
+ sqlQuery: null,
+ exceptionExpected: true,
+ expectedErrorMessage: "Parameter \"{}\" cannot be resolved as column \"id\" with type \"Int32\".",
+ expectedStatusCode: HttpStatusCode.BadRequest
+ );
+ }
+
///
/// Tests the REST Api for FindById operation with attempts at
/// Sql Injection in the primary key route.
diff --git a/src/Service.Tests/SqlTests/RestApiTests/Insert/InsertApiTestBase.cs b/src/Service.Tests/SqlTests/RestApiTests/Insert/InsertApiTestBase.cs
index 74ff7830b0..fea23c18d9 100644
--- a/src/Service.Tests/SqlTests/RestApiTests/Insert/InsertApiTestBase.cs
+++ b/src/Service.Tests/SqlTests/RestApiTests/Insert/InsertApiTestBase.cs
@@ -362,6 +362,32 @@ await SetupAndRunRestApiTest(
);
}
+ ///
+ /// Tests that a cast failure of primary key value type results in HTTP 400 Bad Request.
+ /// e.g. Attempt to cast a string '{}' to the 'publisher_id' column type of int will fail.
+ ///
+ [TestMethod]
+ public async Task InsertWithUncastablePKValue()
+ {
+ string requestBody = @"
+ {
+ ""title"": ""BookTitle"",
+ ""publisher_id"": ""StringFailsToCastToInt""
+ }";
+
+ await SetupAndRunRestApiTest(
+ primaryKeyRoute: string.Empty,
+ queryString: string.Empty,
+ entityNameOrPath: _integrationEntityName,
+ sqlQuery: null,
+ operationType: Operation.Insert,
+ requestBody: requestBody,
+ exceptionExpected: true,
+ expectedErrorMessage: "Parameter \"StringFailsToCastToInt\" cannot be resolved as column \"publisher_id\" with type \"Int32\".",
+ expectedStatusCode: HttpStatusCode.BadRequest
+ );
+ }
+
///
/// Tests the InsertOne functionality with a missing field in the request body:
/// A non-nullable field in the Json Body is missing.
diff --git a/src/Service.Tests/SqlTests/RestApiTests/Patch/PatchApiTestBase.cs b/src/Service.Tests/SqlTests/RestApiTests/Patch/PatchApiTestBase.cs
index fa36113aa6..a9ccc82c51 100644
--- a/src/Service.Tests/SqlTests/RestApiTests/Patch/PatchApiTestBase.cs
+++ b/src/Service.Tests/SqlTests/RestApiTests/Patch/PatchApiTestBase.cs
@@ -473,6 +473,31 @@ await SetupAndRunRestApiTest(
);
}
+ ///
+ /// Tests that a cast failure of primary key value type results in HTTP 400 Bad Request.
+ /// e.g. Attempt to cast a string '{}' to the 'publisher_id' column type of int will fail.
+ ///
+ [TestMethod]
+ public async Task PatchWithUncastablePKValue()
+ {
+ string requestBody = @"
+ {
+ ""publisher_id"": ""StringFailsToCastToInt""
+ }";
+
+ await SetupAndRunRestApiTest(
+ primaryKeyRoute: "id/1",
+ queryString: string.Empty,
+ entityNameOrPath: _integrationEntityName,
+ sqlQuery: null,
+ operationType: Operation.UpsertIncremental,
+ requestBody: requestBody,
+ exceptionExpected: true,
+ expectedErrorMessage: "Parameter \"StringFailsToCastToInt\" cannot be resolved as column \"publisher_id\" with type \"Int32\".",
+ expectedStatusCode: HttpStatusCode.BadRequest
+ );
+ }
+
///
/// Tests the Patch functionality with a REST PATCH request
/// without a primary key route. We expect a failure and so
diff --git a/src/Service.Tests/SqlTests/RestApiTests/Put/PutApiTestBase.cs b/src/Service.Tests/SqlTests/RestApiTests/Put/PutApiTestBase.cs
index 1f556d2d0a..bc5988da8e 100644
--- a/src/Service.Tests/SqlTests/RestApiTests/Put/PutApiTestBase.cs
+++ b/src/Service.Tests/SqlTests/RestApiTests/Put/PutApiTestBase.cs
@@ -643,6 +643,32 @@ await SetupAndRunRestApiTest(
);
}
+ ///
+ /// Tests that a cast failure of primary key value type results in HTTP 400 Bad Request.
+ /// e.g. Attempt to cast a string '{}' to the 'publisher_id' column type of int will fail.
+ ///
+ [TestMethod]
+ public async Task PutWithUncastablePKValue()
+ {
+ string requestBody = @"
+ {
+ ""title"": ""BookTitle"",
+ ""publisher_id"": ""StringFailsToCastToInt""
+ }";
+
+ await SetupAndRunRestApiTest(
+ primaryKeyRoute: "id/1",
+ queryString: string.Empty,
+ entityNameOrPath: _integrationEntityName,
+ sqlQuery: null,
+ operationType: Operation.Upsert,
+ requestBody: requestBody,
+ exceptionExpected: true,
+ expectedErrorMessage: "Parameter \"StringFailsToCastToInt\" cannot be resolved as column \"publisher_id\" with type \"Int32\".",
+ expectedStatusCode: HttpStatusCode.BadRequest
+ );
+ }
+
///
/// Tests the Put functionality with a REST PUT request
/// with the request body having null value for non-nullable column
diff --git a/src/Service/Resolvers/Sql Query Structures/BaseSqlQueryStructure.cs b/src/Service/Resolvers/Sql Query Structures/BaseSqlQueryStructure.cs
index 18bad19b13..8a573d53de 100644
--- a/src/Service/Resolvers/Sql Query Structures/BaseSqlQueryStructure.cs
+++ b/src/Service/Resolvers/Sql Query Structures/BaseSqlQueryStructure.cs
@@ -125,7 +125,11 @@ public Type GetColumnSystemType(string columnName)
}
else
{
- throw new ArgumentException($"{columnName} is not a valid column of {DatabaseObject.Name}");
+ throw new DataApiBuilderException(
+ message: $"{columnName} is not a valid column of {DatabaseObject.Name}",
+ statusCode: HttpStatusCode.BadRequest,
+ subStatusCode: DataApiBuilderException.SubStatusCodes.BadRequest
+ );
}
}
@@ -205,17 +209,14 @@ protected object GetParamAsColumnSystemType(string param, string columnName)
{
return ParseParamAsSystemType(param, systemType);
}
- catch (Exception e)
+ catch (Exception e) when (e is FormatException || e is ArgumentNullException || e is OverflowException)
{
- if (e is FormatException ||
- e is ArgumentNullException ||
- e is OverflowException)
- {
- throw new ArgumentException($"Parameter \"{param}\" cannot be resolved as column \"{columnName}\" " +
- $"with type \"{systemType.Name}\".");
- }
-
- throw;
+ throw new DataApiBuilderException(
+ message: $"Parameter \"{param}\" cannot be resolved as column \"{columnName}\" " +
+ $"with type \"{systemType.Name}\".",
+ statusCode: HttpStatusCode.BadRequest,
+ subStatusCode: DataApiBuilderException.SubStatusCodes.BadRequest,
+ innerException: e);
}
}