Let’s explore how OData POST requests can be used to modify and create new resources in a collection. We’ll use a simple Products collection as the basis for these examples.
To learn more about the OData $filter query, read our blog post here.
Code-Along: Develop an OData Data View in a Responsive Web App
Follow our step-by-step code-along tutorial and learn how to build a web app that connects to an OData service as a data source. This code-along guide is ideal for anyone building custom apps or software on an OData API.
Post Examples – A Simple ScenarioImagine we have an OData service that exposes a Products entity set. Each product has the following properties:
ID (integer)Name (string)Category (string)Price (decimal)StockQuantity (integer)Let’s first explore the simplest of all cases where the client wants to add a new product to the Products collection.
IMPORTANT: The POST body MUST always contain a single valid entity representation.
Here’s our POST request.
POST serviceRoot/Products
Content-Type: application/json
{
"Name": "Laptop",
"Category": "Electronics",
"Price": 1200.00,
"StockQuantity": 50
}To explain, the client sends a POST request to the Products collection’s URL. The request body contains the properties of the new product. The server assigns an ID to the new product and stores it in the Products collection.
Here is what our JSON Response would look like:
{
"ID": 1,
"Name": "Laptop",
"Category": "Electronics",
"Price": 1200.00,
"StockQuantity": 50
}Let’s make this a bit more complex. In this POST request, the client adds a new product but omits the StockQuantity. The server should use a default value for this field.
POST serviceRoot/Products
Content-Type: application/json
{
"Name": "Smartphone",
"Category": "Electronics",
"Price": 800.00
}Note how the StockQuantity is missing in the request. The server assigns a default value (e.g., 0) to the StockQuantity field and generates a ID for the new product.
Here’s our JSON response:
{
"ID": 2,
"Name": "Smartphone",
"Category": "Electronics",
"Price": 800.00,
"StockQuantity": 0
}Next up, the client wants to add a new product and also associate it with an existing category using a relationship. For this example, we assume that the Category field is a navigation property that links to an Categories entity.
Here’s our POST request:
POST serviceRoot/Products
Content-Type: application/json
{
"Name": "Tablet",
"Price": 400.00,
"StockQuantity": 100,
"Category@odata.bind": "serviceRoot/Categories(1)"
}What has changed? The Category@odata.bind property is used to associate the new product with an existing category. The value is the URL to the specific category.
Here’s what our JSON response would look like:
{
"ID": 3,
"Name": "Tablet",
"Price": 400.00,
"StockQuantity": 100,
"Category": {
"ID": 1,
"Name": "Electronics"
}
}Now the client wants to add a new product with additional information, such as dimensions, which is represented as a complex type. The Dimensions property includes Length, Width, and Height.
Here’s our POST request that we send to the OData Products endpoint.
POST serviceRoot/Products
Content-Type: application/json
{
"Name": "Monitor",
"Category": "Electronics",
"Price": 250.00,
"StockQuantity": 20,
"Dimensions": {
"Length": 24.5,
"Width": 14.0,
"Height": 5.5
}
}The Dimensions property is a complex type that groups related information together: it contains length, width, and height.
Our sample JSON response looks like this:
{
"ID": 4,
"Name": "Monitor",
"Category": "Electronics",
"Price": 250.00,
"StockQuantity": 20,
"Dimensions": {
"Length": 24.5,
"Width": 14.0,
"Height": 5.5
}
}Let’s make things even more complex. Now, the client wants to create a new product and simultaneously create a new category for it.
POST Request:
POST serviceRoot/Products
Content-Type: application/json
{
"Name": "Headphones",
"Price": 150.00,
"StockQuantity": 75,
"Category": {
"Name": "Audio Equipment"
}
}In our POST request, the client provides the details for both the Product and the Category. The server creates both the product and the associated category.
Here’s our response payload:
{
"ID": 5,
"Name": "Headphones",
"Price": 150.00,
"StockQuantity": 75,
"Category": {
"ID": 3,
"Name": "Audio Equipment"
}
}Oftentimes, we have to add more than just one product. Here’s how we can add multiple products in a single batch request.
POST serviceRoot/$batch
Content-Type: multipart/mixed; boundary=batch_boundary
--batch_boundary
Content-Type: application/http
Content-Transfer-Encoding: binary
POST serviceRoot/Products
Content-Type: application/json
{
"Name": "Keyboard",
"Category": "Electronics",
"Price": 75.00,
"StockQuantity": 200
}
--batch_boundary
Content-Type: application/http
Content-Transfer-Encoding: binary
POST serviceRoot/Products
Content-Type: application/json
{
"Name": "Mouse",
"Category": "Electronics",
"Price": 40.00,
"StockQuantity": 300
}
--batch_boundary--Batch requests allow the client to send multiple requests in a single HTTP request. Each part of the batch corresponds to a separate POST request.
Our sample JSON response looks like this:
{
"responses": [
{
"status": 201,
"body": {
"ID": 6,
"Name": "Keyboard",
"Category": "Electronics",
"Price": 75.00,
"StockQuantity": 200
}
},
{
"status": 201,
"body": {
"ID": 7,
"Name": "Mouse",
"Category": "Electronics",
"Price": 40.00,
"StockQuantity": 300
}
}
]
}OData’s powerful query language makes it a powerful data access technology.
These examples show how OData POST requests can be used to create new resources in a collection, progressively adding more complex features such as handling missing fields, managing relationships, working with complex types, deep insertion, and batch processing.
Each request sends data to the server, which processes it and responds with the created entities, allowing for efficient and structured data management.