C# WebAPI POST/PUT/PATCH Part 2: Response Handling

John Youngers
Youngers Consulting
3 min readJun 1, 2018

In Part 1 I discussed the overall concept of editing entities at the field level. In this article I’ll go over some ways to simplify handling responses at the API level, and in Part 3 we’ll go over the actual logic of updating the entities.

Your team likely has written both your API as well as your UI: you know how they should work together, and due to that more than likely your API code is not as resilient as it should be. It’s unlikely someone is going to open up Dev Tools and mess around with your API, but what’s more likely is another team or external service will eventually need to consume your API, and if you don’t enjoy answering “why am I getting a ‘500 —Object reference not set to an instance of an object’ response?” all day, I recommend adding some simple null checking:

Anywhere in our code the happy path dictates an object should exist (but in actuality may not), we’re just wrapping it in a EnsureExists() call. If the object is null, it throws an ItemNotFoundException which stops the execution of the rest of our logic. In my use case, usually the classes are named along the lines of Todo for entity classes and TodoViewModel for ViewModels, so I’m assuming the class name will be helpful enough to generate the message (“Todo not found”), but it could be extended for whatever you need, including a custom message as a second parameter to the function. The ItemNotFoundException will bubble up all the way to the API, so we can create a custom handler specifically for this exception to return 404:

Back to the happy path: given the consumer’s API request to update/create an entity, there will be two potential results: Either what they sent in was acceptable and we return a 200 level response, or there were issues with it and we return 400. We can put this process on rails by standardizing the resulting object of all of our save logic:

The gist of your save logic then becomes:

And your API can then respond appropriately:

If the save logic resulted in errors, we return 400 with the message body containing a list of those errors.

If the save logic resulted in a new entity being created, we return a 201 with the message body containing the entity, along with the location header set to the new entity’s url (assuming the paths are following the format /Entities and /Entities/123)

If we’re updating an existing entity, we’ll return 200 with the resulting entity, or 204 if our logic did not set the resulting entity.

In the real world you’d likely need to extend this functionality (maybe you provide a flag on whether to return the refreshed entity, maybe you pull a fresh copy from the database, maybe you have scenarios with compound keys in the url you need to handle, etc), but the core concept would remain.

--

--