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 输出:
我在 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 输出: