none
Can you write to DocumentDB from a Azure Function that is a WebHook? RRS feed

  • Question

  • So yea I get that you can do the whole make a DB function and hit DocumentDB,   however I want to go from WebHook to DocumentDB to a REST response    IE this...

    public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log) .  

    As far as I can tell, this isn't possible.   Am I wrong? I can't even do the imports "using Microsoft.Azure.Documents"   and I tried that #r deal too.


    • Edited by Uloi Friday, January 20, 2017 9:27 PM
    Friday, January 20, 2017 9:24 PM

Answers

  • Andreas is correct.  A Function can have multiple output bindings.  The Function Portal has a template that can get your started.  Let's walk through this with a sample GenericWebhook Function.  Here are the steps:

    1. Visit the Function Portal.

    2. Create a new Function using the GenericWebHook-CSharp template.

    3. Click on Function app settings->Configure app settings.  Under the App setttings view, add a key named AzureWebJobsDocumentDBConnectionString and provide the value for your DocumentDB connection string.  

    4. Click on the Save button to save the new app setting.  Close the Application settings blade and click on your Function name and the Develop button of your newly created Function.

    5. Click on the View Files button and select function.json.  Replace the content of the function.json with the following:

    {  
      "bindings": [
        {  
          "type": "httpTrigger",
          "direction": "in",
          "webHookType": "genericJson",
          "name": "req"
        },    
        { 
          "type": "documentDB",
          "name": "outputDocument",
          "databaseName": "WebHookDb",
          "collectionName": "WebHookCollection",
          "createIfNotExists": true,
          "connection": "AzureWebJobsDocumentDBConnectionString",
          "direction": "out"
        },
        {  
          "type": "http",
          "direction": "out",
          "name": "res"
        }  
      ],  
      "disabled": false
    }


    6. Click on the Save button to save your changes to function.json.

    7. In View Files pane, click on run.csx.  Replace the content of run.csx as follows,

    #r "Newtonsoft.Json"
    
    using System;
    using System.Net;
    using Newtonsoft.Json;
    
    public static async Task<object> Run(HttpRequestMessage req, IAsyncCollector<object> outputDocument, TraceWriter log)
    {
        log.Info($"Webhook was triggered!");
    
        string jsonContent = await req.Content.ReadAsStringAsync();
        dynamic data = JsonConvert.DeserializeObject(jsonContent);
    
        if (data.firstname == null || data.lastname == null || data.email == null) {
            return req.CreateResponse(HttpStatusCode.BadRequest, new {
                error = "Please pass firstname, lastname and email properties in the input object"
            });
        }
    
        var contact = new Contact
        {
            FirstName = data.firstname,
            LastName = data.lastname,
            Email = data.email
        };
    
        await outputDocument.AddAsync(contact);
    
        return req.CreateResponse(HttpStatusCode.OK, new {
            greeting = $"Hello {data.firstname} {data.lastname}!  Your contact info has been saved."
        });
    }
    
    public class Contact
    {
        public string FirstName;
        public string LastName;
        public string Email;
    }

    8. Click on the Save button to save your changes to run.csx.

    9. Click on the Test button to view the test pane.  Replace the content of the Request body with the following,

    {    
        "firstname": "John",
        "lastname": "Doe",
        "email": "johndoe@xyz.com"
    }


    10. Click on the Run button.  

    11. You should see the following in the Output view.

    Status: 200 OK
    {"greeting":"Hello John Doe! Your contact info has been saved."}

    12. You should see the following in the Logs view.

    2017-01-28T08:25:12.262 Function started (Id=e8956416-f5b5-4ce7-9d93-f99a8f246bc1)
    2017-01-28T08:25:12.280 Webhook was triggered!
    2017-01-28T08:25:12.503 Function completed (Success, Id=e8956416-f5b5-4ce7-9d93-f99a8f246bc1)

    13. Visit the DocumentDB Portal and verify that a new entry was added to the WebHookCollection. It should have content similar to the following,

    {
      "FirstName": "John",
      "LastName": "Doe",
      "Email": "johndoe@xyz.com",
      "id": "017be31d-26cb-4038-b7eb-685be747674b"
    }

    I hope this helps!






    • Edited by Ling Toh Saturday, January 28, 2017 9:03 AM
    • Proposed as answer by Kit Foxx Thursday, March 9, 2017 4:18 PM
    • Marked as answer by Sjoukje ZaalMVP, Owner Thursday, March 16, 2017 9:58 AM
    Saturday, January 28, 2017 8:53 AM

All replies

  • You can have multiple outputs from a Function, so you can do both a write to DocDB and return an httpresponse if that's what you mean.

    Or do you need to process things in a sequence where the httpresponse relies on the DocDB action?

    The type of input trigger shouldn't be relevant here. 

    What errors are you seeing on trying to include the DocDB packages? Have you tried including a reference to the NuGets or just the using statement?

    Saturday, January 21, 2017 10:52 AM
  • Andreas is correct.  A Function can have multiple output bindings.  The Function Portal has a template that can get your started.  Let's walk through this with a sample GenericWebhook Function.  Here are the steps:

    1. Visit the Function Portal.

    2. Create a new Function using the GenericWebHook-CSharp template.

    3. Click on Function app settings->Configure app settings.  Under the App setttings view, add a key named AzureWebJobsDocumentDBConnectionString and provide the value for your DocumentDB connection string.  

    4. Click on the Save button to save the new app setting.  Close the Application settings blade and click on your Function name and the Develop button of your newly created Function.

    5. Click on the View Files button and select function.json.  Replace the content of the function.json with the following:

    {  
      "bindings": [
        {  
          "type": "httpTrigger",
          "direction": "in",
          "webHookType": "genericJson",
          "name": "req"
        },    
        { 
          "type": "documentDB",
          "name": "outputDocument",
          "databaseName": "WebHookDb",
          "collectionName": "WebHookCollection",
          "createIfNotExists": true,
          "connection": "AzureWebJobsDocumentDBConnectionString",
          "direction": "out"
        },
        {  
          "type": "http",
          "direction": "out",
          "name": "res"
        }  
      ],  
      "disabled": false
    }


    6. Click on the Save button to save your changes to function.json.

    7. In View Files pane, click on run.csx.  Replace the content of run.csx as follows,

    #r "Newtonsoft.Json"
    
    using System;
    using System.Net;
    using Newtonsoft.Json;
    
    public static async Task<object> Run(HttpRequestMessage req, IAsyncCollector<object> outputDocument, TraceWriter log)
    {
        log.Info($"Webhook was triggered!");
    
        string jsonContent = await req.Content.ReadAsStringAsync();
        dynamic data = JsonConvert.DeserializeObject(jsonContent);
    
        if (data.firstname == null || data.lastname == null || data.email == null) {
            return req.CreateResponse(HttpStatusCode.BadRequest, new {
                error = "Please pass firstname, lastname and email properties in the input object"
            });
        }
    
        var contact = new Contact
        {
            FirstName = data.firstname,
            LastName = data.lastname,
            Email = data.email
        };
    
        await outputDocument.AddAsync(contact);
    
        return req.CreateResponse(HttpStatusCode.OK, new {
            greeting = $"Hello {data.firstname} {data.lastname}!  Your contact info has been saved."
        });
    }
    
    public class Contact
    {
        public string FirstName;
        public string LastName;
        public string Email;
    }

    8. Click on the Save button to save your changes to run.csx.

    9. Click on the Test button to view the test pane.  Replace the content of the Request body with the following,

    {    
        "firstname": "John",
        "lastname": "Doe",
        "email": "johndoe@xyz.com"
    }


    10. Click on the Run button.  

    11. You should see the following in the Output view.

    Status: 200 OK
    {"greeting":"Hello John Doe! Your contact info has been saved."}

    12. You should see the following in the Logs view.

    2017-01-28T08:25:12.262 Function started (Id=e8956416-f5b5-4ce7-9d93-f99a8f246bc1)
    2017-01-28T08:25:12.280 Webhook was triggered!
    2017-01-28T08:25:12.503 Function completed (Success, Id=e8956416-f5b5-4ce7-9d93-f99a8f246bc1)

    13. Visit the DocumentDB Portal and verify that a new entry was added to the WebHookCollection. It should have content similar to the following,

    {
      "FirstName": "John",
      "LastName": "Doe",
      "Email": "johndoe@xyz.com",
      "id": "017be31d-26cb-4038-b7eb-685be747674b"
    }

    I hope this helps!






    • Edited by Ling Toh Saturday, January 28, 2017 9:03 AM
    • Proposed as answer by Kit Foxx Thursday, March 9, 2017 4:18 PM
    • Marked as answer by Sjoukje ZaalMVP, Owner Thursday, March 16, 2017 9:58 AM
    Saturday, January 28, 2017 8:53 AM