【问题标题】:Azure C# function - how to send through the full request into the output documentAzure C# 函数 - 如何将完整请求发送到输出文档
【发布时间】:2021-10-14 03:25:03
【问题描述】:

我有一个几乎已经构建好的 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
}

【问题讨论】:

  • Stream sgBody 更改为string sgBody 并在CheckValidity 方法中执行Body = sgBody。用CheckValidity(sgEventValid, log, documentsOut, requestBody)调用CheckValidity方法
  • 啊,谢谢@Chetan!但是,现在我的输出看起来像: { "sgBody": "[{\"category\":[\"develop\",\"...tls\":1}]\r\n", "id ": "6807b2bc-7d45-4bef-aaec-e2f19c568503", "_rid": "2WwUAKT2MsthKwAAAAAAAAA==", "_self": "dbs/2WwUAA==/colls/2WwUAKT2Mss=/docs/2WwUAKT2MsthKwAAAAAAA==/", "_etag ": "\"1301cdda-0000-1a00-0000-6167a7b30000\"", "_attachments": "attachments/", "_ts": 1634183091 } 所以整个事情都是一个长字符串,而不是正确的 CR/LF有\r\n的。
  • 这个网站的代码太多了。请参阅minimal reproducible example。与问题的内容相比,您发布的代码太多了。
  • Ahhh OK @KenWhite - 已将代码缩减为仅指示我在做什么。对不起!

标签: c# azure-functions


【解决方案1】:

好的,我自己做到了。这对于使用 Azure 函数来使用 SendGrid 事件的任何人都特别有帮助,这些事件随后会写入 Cosmos 数据库,但在其他情况下显然也很有用。我还添加了标题,它以 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 输出:

【讨论】:

    猜你喜欢
    • 2014-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多