I'm not sure what you're doing inside of EmailActivityFromWebhook, so I can't help you with that.
Here's a sample to receive the SendGrid events, and then use JSON.NET to parse the JSON Array, and extract the values you want.
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using System.Web.Mvc;
namespace SendGridEvents.Controllers
{
public class SendGridController : Controller
{
[HttpPost()]
[Route("SendGridEvent")]
public async Task<ActionResult> Event()
{
JArray events;
using (var jsonReader = new JsonTextReader(new StreamReader(Request.InputStream)))
{
var serializer = new JsonSerializer();
events = serializer.Deserialize<JArray>(jsonReader);
}
foreach (JObject sendGridEvent in events){
var eventId = sendGridEvent["sg_event_id"];
var eventType = sendGridEvent["event"];
var email = sendGridEvent["email"];
Debug.WriteLine($"Event ID: {eventId}");
Debug.WriteLine($"Event Type: {eventType}");
Debug.WriteLine($"Email: {email}");
}
return new HttpStatusCodeResult(System.Net.HttpStatusCode.OK);
}
}
}
You could also use strongly-typed objects and have MVC bind the JSON to objects, but it gets a little complicated because depending on the event JSON property, there may be more or less properties in the JSON object. (See Event Webhook docs for different event type JSON)
By using JSON.NET with a JArray and then inspecting individual JObject's, you can extract the event property and use different logic as necessary by your requirements.
If this doesn't help, let us know what you're looking for.
Update 1: OP clarified they use ASP.NET Core
Here's the ASP.NET Core equivalent using System.Text.Json instead of JSON.NET:
using System.Text.Json;
using Microsoft.AspNetCore.Mvc;
namespace SendGridEvents.Controllers;
public class SendGridController : Controller
{
private readonly ILogger<SendGridController> logger;
public SendGridController(ILogger<SendGridController> logger)
{
this.logger = logger;
}
[HttpPost("SendGridEvent")]
public async Task<ActionResult> Event()
{
using (JsonDocument document = await JsonDocument.ParseAsync(Request.Body))
{
foreach (JsonElement sendGridEvent in document.RootElement.EnumerateArray())
{
var eventId = sendGridEvent.GetProperty("sg_event_id").GetString();
var eventType = sendGridEvent.GetProperty("event").GetString();
var email = sendGridEvent.GetProperty("email").GetString();
logger.LogInformation("Event ID: {EventId}", eventId);
logger.LogInformation("Event Type: {EventType}", eventType);
logger.LogInformation("Email: {Email}", email);
}
}
return Ok();
}
}
With ASP.NET Core you can even use parameter binding which makes this simpler:
[HttpPost("SendGridEvent")]
public ActionResult Event([FromBody]JsonDocument document)
{
foreach (JsonElement sendGridEvent in document.RootElement.EnumerateArray())
{
var eventId = sendGridEvent.GetProperty("sg_event_id").GetString();
var eventType = sendGridEvent.GetProperty("event").GetString();
var email = sendGridEvent.GetProperty("email").GetString();
logger.LogInformation("Event ID: {EventId}", eventId);
logger.LogInformation("Event Type: {EventType}", eventType);
logger.LogInformation("Email: {Email}", email);
}
return Ok();
}
You can still bind this JSON to an array or list of strongly-typed objects if you'd like, but with the same caveats as mentioned before.