-
Notifications
You must be signed in to change notification settings - Fork 14
Tutorial 02 17 Adding Patch Endpoints

The term Patch is used to describe an operation where an entity is partially updated.
In Harmony Core, as in many other RESTful web service implementations, an HTTP PATCH operation is used to perform a patch operation for an entity.
When performing an HTTP PATCH there are several requirements that the client must comply with in order for an entity to be patched. The client must:
-
Include in the body of the HTTP request a valid JSON Patch Document that describes one or more changes that are to be applied to an existing entity
-
Include an HTTP request header named
Content-Typethat identifies the type of data being sent in the request body as being of typeapplication/json. -
Include an HTTP request header named
Content-Lengththat specifies the length of the data (in bytes) being sent in the request body. Note that some client tools, including Postman, will add this header automatically based on the data you pass.
To generate endpoints that allow clients to patch entities via HTTP PATCH operations, you must enable the ENABLE_PATCH option:
-
Edit
regen.batand remove the rem comment from the beginning of the line, like this:set ENABLE_PATCH=-define ENABLE_PATCH
-
Save your changes to
regen.bat. -
If you don't already have a command prompt open in the solution folder, use the
Tools > Command Prompt (x64)menu option to open a Windows command prompt, and type the following command:cd .. -
Type the following command to regenerate your code:
regen
As the batch file executes, you will see various messages confirming which source files are being generated.
- Look for the word
DONEto indicate that all code generation tasks completed successfully.
Enabling the ENABLE_PATCH option causes an additional endpoint method to be added to each of the generated OData Controller classes. The new method (with most of the code removed from the procedure division) looks something like this:
{HttpPatch("Customers(CustomerNumber={aCustomerNumber})")}
{Produces("application/json")}
{ProducesResponseType(StatusCodes.Status204NoContent)}
{ProducesResponseType(StatusCodes.Status400BadRequest)}
{ProducesResponseType(StatusCodes.Status404NotFound)}
;;; <summary>
;;; Patch (partial update) a customer.
;;; </summary>
;;; <param name="aCustomerNumber">Customer number</param>
;;; <returns>Returns an IActionResult indicating the status of the operation and containing any data that was returned.</returns>
public method PatchCustomer, @IActionResult
{FromODataUri}
required in aCustomerNumber, int
{FromBody}
required in aCustomer, @JsonPatchDocument<Customer>
proc
;; Validate inbound data
if (!ModelState.IsValid)
mreturn ValidationHelper.ReturnValidationError(ModelState)
mreturn NoContent()
endmethod
The sample code above was taken from CustomersController.dbl, and as you can see, the code accepts two parameters:
-
A parameter named
aCustomerNumberwhich is the primary key value for the entity to be patched.- Notice that the parameter is decorated with an attribute
{FromODataUri}, indicating that the data must be provided via a URL parameter of the HTTP request.
- Notice that the parameter is decorated with an attribute
-
A parameter named
aCustomerwhich is a JSON Patch Document of type customer, containing the change instructions that are to be applied to the existing customer entity.- Notice that the parameter is decorated with an attribute
{FromBody}, indicating that the patch document must be provided via the body of the HTTP request.
- Notice that the parameter is decorated with an attribute
The little bit of code that we left in the procedure division does two things:
-
It checks the value of
ModelState.IsValid, and if it's false, it returns an error.- Code that has already executed in the ASP.NET Core pipeline has already inspected the inbound data from the client, and if that data is determined to be invalid for any reason, then ModelState.IsValid is set to false. By returning
ValidationHelper.ReturnValidationError(ModelState), we ensure that the client will receive anHTTP 400 (bad request)response, and also that information about the invalid data will be included in the body of the response to the client.
- Code that has already executed in the ASP.NET Core pipeline has already inspected the inbound data from the client, and if that data is determined to be invalid for any reason, then ModelState.IsValid is set to false. By returning
-
On successful completion a
NoContent()response is returned. This will result in anHTTP 204 (no content)response to the client.
You will find similar new code in all of your other controllers.
If you are generating Postman Tests, a new PATCH request is added to the folder for each entity type, but you will need to re-import the newly generated tests into Postman. The instructions will walk you through doing this later.
-
Select
Build > Rebuild Solutionfrom the Visual Studio menu. -
Check the
Outputwindow. You should see something like this:1>------ Rebuild All started: Project: Repository, Configuration: Debug Any CPU ------ 2>------ Rebuild All started: Project: Services.Models, Configuration: Debug Any CPU ------ 3>------ Rebuild All started: Project: Services.Controllers, Configuration: Debug Any CPU ------ 4>------ Rebuild All started: Project: Services.Isolated, Configuration: Debug Any CPU ------ 5>------ Rebuild All started: Project: Services, Configuration: Debug Any CPU ------ 6>------ Rebuild All started: Project: Services.Host, Configuration: Debug Any CPU ------ ========== Rebuild All: 6 succeeded, 0 failed, 0 skipped ==========
- In Visual Studio, press
F5(start debugging) to start the self-hosting application. Once again, you should see the console window appear, with the messages confirming that your service is running.
It is not possible to test the functionality of the new endpoints using a web browser because the functionality to be tested involves issuing an HTTP PATCH request. Our tool of choice for issuing PATCH requests is Postman.
-
Start
Postmanand close any request tabs that may be open. -
Select
File > Importfrom the Postman menu. -
In the
IMPORTdialog, click theChoose Filesbutton. -
Browse to your main solution folder, select the
PostMan_ODataTests.postman_collectionfile, and then click theOpenbutton. -
Back in the
IMPORTdialog, click theImportbutton. -
In the
COLLECTION EXISTSdialog, click theReplacebutton.
Postman will now re-load the tests in the Harmony Core Sample API collection, and you will notice that the total number of tests increases.
- Open the
Customer Testsfolder and select thePATCH Patch customerrequest.
You will notice that:
-
The HTTP method is set to
PATCH. -
The URL is set to
{{ServerBaseUri}}/{{ODataPath}}/v{{ApiVersion}}/Customers(CustomerNumber=123). -
Click on the
Headerstab and you will see that theContent-Typeheader is set toapplication/json. -
Click on the
Bodytab and you will see that the request contains a sample JSON patch document.[ { "op": "replace", "path": "PropertyName", "value": "PropertyValue" } ]
-
Change the value of the
CustomerNumberparameter in the URL to1. -
In the request body, change the JSON patch document so that it looks like this:
[
{
"op": "replace",
"path": "Street",
"value": "123 Main St."
},
{
"op": "replace",
"path": "City",
"value": "Roseville"
},
{
"op": "replace",
"path": "ZipCode",
"value": "95747"
}
]
First, let's examine the current data for customer 1.
- Select the
GET Read Customerrequest, change the value of theCustomerNumberparameter in the URL to1and click the big blueSendbutton.
You should see that customer 1 currently looks like this:
{
"@odata.context": "https://localhost:8086/odata/v1/$metadata#Customers/$entity",
"@odata.etag": "W/\"YmluYXJ5J0FDQUFBQUFBNHhsU3FRPT0n\"",
"CustomerNumber": 1,
"Name": "San Pablo Nursery",
"Street": "1324 San Pablo Dam Road",
"City": "San Pablo",
"State": "CA",
"ZipCode": 94806,
"Contact": "Karen Graham",
"Phone": "(555) 912-2341",
"Fax": "(555) 912-2342",
"FavoriteItem": 13,
"PaymentTermsCode": "01",
"TaxId": 559244251,
"CreditLimit": 2000.00,
"GlobalRFA": "ACAAAAAA4xlSqQ=="
}
- Now switch back to the
PATCH Patch customerrequest and click the big blueSendbutton.
You should see a response of '204 No Content', indicating a successful PATCH.
- Once again, select the
GET Read Customerrequest and click the big blueSendbutton.
You should see that customer 1 now looks like this:
{
"@odata.context": "https://localhost:8086/odata/v1/$metadata#Customers/$entity",
"@odata.etag": "W/\"YmluYXJ5J0FDQUFBQUFBdHRqVXh3PT0n\"",
"CustomerNumber": 1,
"Name": "San Pablo Nursery",
"Street": "123 Main St.",
"City": "Roseville",
"State": "CA",
"ZipCode": 95747,
"Contact": "Karen Graham",
"Phone": "(555) 912-2341",
"Fax": "(555) 912-2342",
"FavoriteItem": 13,
"PaymentTermsCode": "01",
"TaxId": 559244251,
"CreditLimit": 2000.00,
"GlobalRFA": "ACAAAAAAttjUxw=="
}
Notice that the values of the Street, City, and ZipCode properties have been patched to the values you provided.
- When you are done with your testing, stop the self-hosting application.
Enabling patch endpoints adds endpoints to all of your code generated OData Controllers, but it is possible to prevent the generation of these endpoints for certain structures. This capability is documented in structure specific endpoint control.
Next topic: Adding Delete Endpoints
-
Tutorial 2: Building a Service from Scratch
- Creating a Basic Solution
- Enabling OData Support
- Configuring Self Hosting
- Entity Collection Endpoints
- API Documentation
- Single Entity Endpoints
- OData Query Support
- Alternate Key Endpoints
- Expanding Relations
- Postman Tests
- Supporting CRUD Operations
- Adding a Primary Key Factory
- Adding Create Endpoints
- Adding Upsert Endpoints
- Adding Patch Endpoints
- Adding Delete Endpoints
-
Harmony Core CLI Tool
-
OData Aware Tools
-
Advanced Topics
- CLI Tool Customization
- Adapters
- API Versioning
- Authentication
- Authorization
- Collection Counts
- Customization File
- Custom Field Types
- Custom File Specs
- Custom Properties
- Customizing Generated Code
- Deploying to Linux
- Dynamic Call Protocol
- Environment Variables
- Field Security
- File I/O
- Improving AppSettings Processing
- Logging
- Optimistic Concurrency
- Multi-Tenancy
- Publishing in IIS
- Repeatable Unit Tests
- Stored Procedure Routing
- Suppressing OData Metadata
- Traditional Bridge
- Unit Testing
- EF Core Optimization
- Updating a Harmony Core Solution
- Updating to 3.1.90
- Creating a new Release
-
Background Information
