Azure C# 函数 - 如何将完整请求发送到输出文档

Azure C# function - how to send through the full request into the output document

我在 C# 中有一个 Azure 函数,我几乎已经构建好了。它被设置为从 SendGrid 接收数据,验证数据,然后将数据写入 Cosmos。这是代码:

namespace SendGrid.CosmosLogging
{
    public static class SendGrid_Logging
    {
        [FunctionName("SendGrid_Logging")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req,
            [CosmosDB(
                databaseName: "portal-dev",
                collectionName: "sendgrid",
                ConnectionStringSetting = "CosmosDbConnectionString")]
            IAsyncCollector<dynamic> documentsOut,
            ILogger log)
        {

        try
        {
            log.LogInformation("SendGrid C# HTTP trigger function started processing a request.");
            
            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            var headers = req.Headers;
            var sgbody = req.Body;

            //Check validity
            CheckValidity(log, documentsOut, sgbody);   //req.Body - has to be Stream object

        }
        catch (Exception e)
        {
            log.LogInformation("Error validating SendGrid event, error is: "+ e.ToString());
            throw;
        }
        
    }

    private static async void CheckValidity(ILogger log, IAsyncCollector<dynamic> documentsOut, Stream sgBody)
    {
        // Add a JSON document to the output container.
        await documentsOut.AddAsync( new
        {
            //Write the sendgrid body only to the Cosmos container
            sgBody
            //Body = "This is something"
            //name = name
        });
        responseMessage =
            "The SendGrid HTTP triggered function executed successfully processing Id: ";//${doc_id}
        log.LogInformation(responseMessage);
    }
    
}

}

问题是在 CheckValidity 方法中写入 sgBody 的行。这永远不会影响到 Cosmos 容器。但是,如果将其替换为:

            // Add a JSON document to the output container.
            await documentsOut.AddAsync( new
            {
                //Write the sendgrid body only to the Cosmos container
                //sgBody
                Body = "This is something"
                //name = name
            });

然后我在 Cosmos 中得到如下所示的输出:

{
    "Body": "This is something",
    "id": "e65c2efe-79d2-4997-b1b2-33833dbf14ce",
    "_rid": "2WwUAKT2MsvdKgAAAAAAAA==",
    "_self": "dbs/2WwUAA==/colls/2WwUAKT2Mss=/docs/2WwUAKT2MsvdKgAAAAAAAA==/",
    "_etag": "\"12015ff1-0000-1a00-0000-61679d8c0000\"",
    "_attachments": "attachments/",
    "_ts": 1634180492
}

所以我的问题是,如何获取要写入的 sgBody 变量的全部内容?这里有一些我明显遗漏的东西(我不是 C# 开发人员,但我正在尽力而为!)。

编辑:

我希望作为输出到 Cosmos 容器的格式是格式正确的 JSON 正文,类似于:

{
   "body":{
      "timestamp":1631141801,
      "sg_template_name":"Receiver - NonProd",
      "ip":"149.72.246.163",
      "tls":1,
      "smtp-id":"<2MhvBnobRN-KQNdFF9cO4w@geopod-ismtpd-5-0>",
      "email":"somewhere@something.com",
      "response":"250 2.6.0 <2MhvBnobRN-KQNdFF9cO4w@geopod-ismtpd-5-0> [InternalId=300647724419, Hostname=SY4P282MB3809.AUSP282.PROD.OUTLOOK.COM] 289934 bytes in 0.131, 2154.683 KB/sec Queued mail for delivery",
      "sg_message_id":"2MhvBnobRN-KQNdFF9cO4w.filterdrecv-75ff7b5ffb-vm78l-1-61393FA4-43.0",
      "event":"delivered",
      "sg_event_id":"ZGVsaXZlcmVkLTAtMjI4MDI0MTAtMk1odkJub2JSTi1LUU5kRkY5Y080dy0w",
      "sg_template_id":"d-04096fb423674bdf8870dfc92eec944f",
      "category":[
         "develop",
         "Something"
      ]
   },
   "id":"0c4143fa-d5a2-43e8-864f-82f333ace3cd",
   "_rid":"SL81APS-4Q21KQAAAAAAAA==",
   "_self":"dbs/SL81AA==/colls/SL81APS-4Q0=/docs/SL81APS-4Q21KQAAAAAAAA==/",
   "_etag":"\"7700726c-0000-1a00-0000-61393fb20000\"",
   "_attachments":"attachments/",
   "_ts":1631141810
}

好的,我自己设法做到了。这对于使用 Azure 函数来使用 SendGrid 事件的任何人都特别有帮助,这些事件随后被写入 Cosmos 数据库,但显然在其他情况下也很有用。我还添加了 headers,它作为 iHeaderDictionary 类型出现,当您需要标准 JSON.

时,使用它有点困难
namespace SendGrid.CosmosLogging
{
    public static class SendGrid_Logging
    {
        [FunctionName("SendGrid_Logging")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
            HttpRequest req,
            [CosmosDB(
                databaseName: "portal-dev",
                collectionName: "sendgrid",
                ConnectionStringSetting = "CosmosDbConnectionString")]
            IAsyncCollector<dynamic> documentsOut,
            ILogger log)
        {

        try
        {
            log.LogInformation("SendGrid C# HTTP trigger function started processing a request.");
            
            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            var headers = req.Headers;
            var sgbody = req.Body;

            //Create a new dictionary and fill it with the items in the existing headers. This is done due to needing to
            //convert the headers to a dynamic object for the Cosmos write. Can only easily stringify a Dictionary object,
            //but not the specific HttpRequest header object, so have to convert.
            Dictionary<string,string> ihHeaders = new Dictionary<string,string>
            {};
            foreach (var item in req.Headers)
            {
                ihHeaders.Add(item.Key,item.Value);
            }
            string jsonHeaders = JsonConvert.SerializeObject(ihHeaders,Formatting.Indented);

            //Use these dynamic objects for writing to Cosmos
            dynamic sendgriddata = JsonConvert.DeserializeObject(requestBody);
            dynamic sendgridheaders = JsonConvert.DeserializeObject(jsonHeaders);

            //Check validity
            CheckValidity(log, documentsOut, sendgriddata, sendgridheaders);   //req.Body - has to be Stream object

        }
        catch (Exception e)
        {
            log.LogInformation("Error validating SendGrid event, error is: "+ e.ToString());
            throw;
        }
        
    }

    private static async void CheckValidity(ILogger log, IAsyncCollector<dynamic> documentsOut, dynamic sgBody, dynamic sgHeaders)
    {
        // Add a JSON document to the output container.
        await documentsOut.AddAsync( new
        {
            //Write the sendgrid body only to the Cosmos container
            headers = sgHeaders
            body = sgBody
        });
        responseMessage =
            "The SendGrid HTTP triggered function executed successfully processing Id: ";//${doc_id}
        log.LogInformation(responseMessage);
    }
    
}

这在 Cosmos 中提供了格式良好的 JSON 输出: