2

I have been searching for a technique to use Azure Functions to delete items in a Cosmos database, using the in-browser code editor. Theres various reasons on my side why I dont want to use locally-developed code on VS.

The code I am using is available here, I am using a HttpTrigger with a CosmosDB input and output binding. They are named fairly obviously (inputDocument, outputDocument).

This code is working amazingly for reading items from the db, and writing new documents, however I want to be able to delete a single item. I'm making a game 'auction house' system, and to 'buy' an item, I need to remove it from the db.

I have searched a fair few places now, many people say to use DocumentDB, but I dont think browser-editor can support this, I cant get it to recognise the correct Azure libraries to be able to use this. If I'm missing a step, please let me know. Its failing when I add

#r "Microsoft.Azure.Documents.Client"
using Microsoft.Azure.Documents.Client;

EDIT After talking with Azure Support, I have found out that v3 uses Documents.Core, not Documents.Client. If anyone can supply docs for Documents.Core I will be thankful!

Thanks. Code copied below;

    #r "Newtonsoft.Json"

    using System.Net;
    using System.Linq;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Primitives;
    using Newtonsoft.Json;

    public class AuctionItem
    {
        [JsonProperty("itemID")]
        public string itemID { get; set; }
    
        [JsonProperty("price")]
        public string Price { get; set; }
    
        [JsonProperty("amount")]
        public string Amount { get; set; }
    }

    public static IActionResult Run(HttpRequest req, out object outputDocument, 
    IEnumerable<AuctionItem> inputDocument, ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request.");

        string name = req.Query["name"];
        string price = req.Query["price"];
        string amount = req.Query["amount"];

        string command = req.Query["command"];

        outputDocument = null;

        if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(price) && !string.IsNullOrEmpty(amount)) 
        {
            string responseMessage = "{\"Message\":\"Success\",\n\"Data\": [" + "\n";
               
            if (!string.IsNullOrEmpty(command)) {
                if (command == "1") {
                    foreach (var item in inputDocument) {
                        responseMessage += "{\n\t\"itemID\":\"" + item.itemID + "\"," + "\n";
                        responseMessage += "\t\"price\":\"" + item.Price + "\"," + "\n";
                        responseMessage += "\t\"amount\":\"" + item.Amount + "\"}," + "\n";
                    }
                } else if (command == "2") {
                    var item = inputDocument.Where(x => x.itemID == name).FirstOrDefault();
                    if (item != null) {
                        inputDocument = inputDocument.Where(x => x != item);
                    }
                } else if (command == "3") {
                    responseMessage += "{\n\t\"itemID\":\"" + name + "\",\n";
                    responseMessage += "\t\"price\":\"" + price + "\",\n";
                    responseMessage += "\t\"amount\":\"" + amount + "\"}\n";
                

                    log.LogInformation(responseMessage);
                    outputDocument = new {
                        itemID = name,
                        price = price,
                        amount = amount
                    };
                }
            }
        
            responseMessage += "]}";
            return new OkObjectResult(responseMessage);
        } else {
            outputDocument = null;
            return new BadRequestResult();
        }
            
    }

Dracon
  • 81
  • 1
  • 7

1 Answers1

1

You need to create a file named "function.proj" in your http trigger.

Content:

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFramework>netcoreapp3.0</TargetFramework>
    </PropertyGroup>
    <ItemGroup>
        <PackageReference Include="Microsoft.Azure.DocumentDB.Core" Version="2.12.0" />
    </ItemGroup>
</Project>

Create step:

1.switch to classic experience enter image description here

2.create file enter image description here

Below is my test code, and it can work fine:

#r "Newtonsoft.Json"
#r "Microsoft.Azure.DocumentDB.Core"

using System.Net;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using System;
using System.Threading.Tasks;

private static DocumentClient client;

public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
    log.LogInformation("C# HTTP trigger function processed a request.");

    client = new DocumentClient(new Uri("endpointUrl"), "authorizationKey");
    ResourceResponse<Document> response = await client.DeleteDocumentAsync(
        UriFactory.CreateDocumentUri("databaseName", "collectionName", "id"),
        new RequestOptions { PartitionKey = new PartitionKey("partition-key-value") });

    log.LogInformation("Request charge of delete operation: {0}", response.RequestCharge);
    log.LogInformation("StatusCode of operation: {0}", response.StatusCode);


    return new OkResult();    
}

By the way, you can find docs here.

Steve Johnson
  • 8,057
  • 1
  • 6
  • 17
  • That bit of magic at the start seems to have made my code accept DocumentClient! Thank you so much for your help :) – Dracon Oct 13 '20 at 13:09
  • Apologies for adding to the question, but how would you go about running the Run function as an asyncronous task, but keeping the 'out outputDocument' for the output binding? Async functions cant have out variables – Dracon Oct 13 '20 at 13:10
  • 1
    async methods don't support out-by-reference parameters. you can use `CreateDocumentAsync()` method instead of out parameter. – Steve Johnson Oct 14 '20 at 02:45