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.