Updating Trip Data With Azure Functions and Cosmos DB

In my previous post I reviewed the simple code used to create new trip entries in Cosmos DB from an POST to an Azure Function. For this post I will be reviewing the code needed for a PUT request to an Azure Function that will update trip data in Cosmos DB. The next version of the project adds another Azure function for handling PUT requests.

Update Trigger/Binding

The UpdateTripRequest Azure function in the TripLoggerServices project supports updating existing trips stored in Cosmos DB. The function uses the HttpTrigger attribute to trigger the function from an HTTP PUT request. The CosmosDB attribute is used to look up the trip entry in Cosmos DB based on the submitted tripId.

public static class UpdateTripRequest
{
	[FunctionName("UpdateTripRequest")]
	public static async Task<IActionResult> Run(
		[HttpTrigger(AuthorizationLevel.Anonymous, "put", Route = "trips/{tripId}")] HttpRequest req,
		string tripId,
		[CosmosDB(
			databaseName: "TripLog",
			collectionName: "Trips",
			CreateIfNotExists = true,
			Id = "{tripId}",
			ConnectionStringSetting = "CosmosDBConnection")]TripEntry tripEntry,
		ILogger log)
	{
	}
}

HttpTrigger

The HttpTrigger attribute is configured to bind the HttpRequest to the req function parameter (line 5) and the route parameter “trips/{tripId}” to the string tripId function parameter (line 6). The binding is configured to only respond to PUT requests by passing “put” to the methods parameter.

Cosmos Input Binding

To retrieve a record from Cosmos DB by Id the Id = “{tripId}” parameter of the CosmosDB attribute is used. By setting the value to a template string the attribute knows to use the value for tripId set by the HttpTrigger (line 11). If the trip entry is found in Cosmos DB the tripEntry parameter will contain the retrieved record. If the trip entry is not found the tripEntry parameter will be null.

Processing the Request

Much of processing the PUT request is very similar to the POST request. The differences revolve around determining if the trip entry was found and updating the found trip entry.

if(tripEntry == null)
{
	return new NotFoundObjectResult($"Could not find trip entry with id: {tripId}");
}

// get raw request body
var requestBody = new StreamReader(req.Body).ReadToEnd();
var putRequest = JsonConvert.DeserializeObject<TripPut>(requestBody);

if (string.IsNullOrWhiteSpace(putRequest.TripFrom)) return new BadRequestObjectResult($"{nameof(putRequest.TripFrom)} missing");
if (string.IsNullOrWhiteSpace(putRequest.TripTo)) return new BadRequestObjectResult($"{nameof(putRequest.TripTo)} missing");
if (string.IsNullOrWhiteSpace(putRequest.Description)) return new BadRequestObjectResult($"{nameof(putRequest.Description)} missing");
if (putRequest.Distance == null) return new BadRequestObjectResult($"{nameof(putRequest.Distance)} missing");

tripEntry.Date = putRequest.Date;
tripEntry.Distance = putRequest.Distance;
tripEntry.TripFrom = putRequest.TripFrom;
tripEntry.TripTo = putRequest.TripTo;
tripEntry.Description = putRequest.Description;
tripEntry.ModifiedOn = DateTime.UtcNow;

// return results
return new OkObjectResult($"{tripId}");

First the tripEntry is checked for null, if the parameter is null we know that the entity was not found in CosmosDB and return a 404 response (lines 1-4). Next, like in the POST request, the update request is deserialized into a TripPut dto and some simple validation is performed (lines 7-13). Last, the updates are copied over from the TripPut dto to the tripEntry object and a OK(200) result is returned with the tripId as content (lines 15-20,23). The important thing to note here is that by virtue of the CosmosDB attribute any changes made to the tripEntry object is automatically updated in Cosmos DB when the function successfully finishes processing.

With the addition of the UpdateTripRequest Azure function it is now possible to update previously logged trips in Cosmos DB. More to come as the TripLoggerService evolves.

Leave a comment