Configuring Azure Monitor Action Groups to trigger webhooks is a powerful way to automate incident response. However, once Azure fires that HTTP POST request containing your alert payload, your application needs a secure, well-structured endpoint to ingest, parse, and act upon it.
While tools like Logic Apps or third-party incident platforms (such as PagerDuty or Slack) handle many integrations out of the box, building a custom webhook receiver in ASP.NET Core gives you absolute control. You can log alerts to your internal systems, trigger automated self-healing scripts, or dispatch custom notifications across your organization.
In this comprehensive guide, we will walk through defining strongly-typed models for the Azure Monitor Common Alert Schema, implementing a secure ASP.NET Core API controller, and safeguarding your endpoint against unauthorized traffic.
Why Build a Custom Webhook Endpoint?
Writing your own webhook receiver provides key operational advantages:
Total Customization: Process alert data exactly how your business logic requires.
Unified Logging: Ingest cloud alerts directly into your application's centralized logging pipeline (like Serilog and Application Insights).
Automated Remediation: Trigger background tasks or domain commands (via MediatR) to attempt automated recovery when specific alerts fire.
Step 1: Defining DTOs for the Common Alert Schema
When you enable the Common Alert Schema in your Azure Action Group, Azure guarantees a predictable, normalized JSON payload format regardless of whether the alert originated from a metric rule, a log query, or an activity log.
Create strongly-typed C# models in your API project to map this incoming structure cleanly:
C#
namespace YourSolution.API.Models
{
public class AzureAlertPayload
{
public string SchemaId { get; set; } = string.Empty;
public AlertData Data { get; set; } = new();
}
public class AlertData
{
public AlertEssentials Essentials { get; set; } = new();
public object? AlertContext { get; set; }
}
public class AlertEssentials
{
public string AlertId { get; set; } = string.Empty;
public string AlertRule { get; set; } = string.Empty;
public string Severity { get; set; } = string.Empty;
public string SignalType { get; set; } = string.Empty;
public string MonitorCondition { get; set; } = string.Empty;
public string MonitoringService { get; set; } = string.Empty;
public DateTime FiredDateTime { get; set; }
public string Description { get; set; } = string.Empty;
}
}
Step 2: Implementing the Webhook Controller
Next, create an API controller that exposes a secure POST endpoint. This controller will deserialize the incoming alert payload, log essential metrics, and return a 200 OK status code so Azure knows the notification was successfully delivered.
C#
using Microsoft.AspNetCore.Mvc;
using YourSolution.API.Models;
namespace YourSolution.API.Controllers
{
[Route("api/webhooks")]
[ApiController]
public class WebhookController : ControllerBase
{
private readonly ILogger<WebhookController> _logger;
public WebhookController(ILogger<WebhookController> logger)
{
_logger = logger;
}
[HttpPost("azure-alert")]
public IActionResult ReceiveAzureAlert([FromBody] AzureAlertPayload payload)
{
if (payload?.Data?.Essentials == null)
{
_logger.LogWarning("Received malformed Azure alert payload.");
return BadRequest(new { message = "Invalid alert payload format." });
}
var alert = payload.Data.Essentials;
// Log the alert details with appropriate severity
_logger.LogWarning(
"Azure Alert Fired! Rule: {RuleName}, Severity: {Severity}, Condition: {Condition}, Time: {Time}, Description: {Description}",
alert.AlertRule,
alert.Severity,
alert.MonitorCondition,
alert.FiredDateTime,
alert.Description);
// TODO: Implement custom downstream logic here
// (e.g., trigger automated remediation, dispatch internal events, or record the incident).
return Ok(new { status = "Success", message = "Alert processed successfully." });
}
}
}
Step 3: Securing Your Webhook Endpoint
Because your webhook endpoint must be publicly accessible over the internet for Azure Monitor to reach it, security is paramount. Anyone who discovers your URL could potentially send fake alert requests.
You can secure your endpoint using industry-standard practices:
1. Secret Token Validation via Query Parameters or Headers
Append a secure secret token directly inside your Azure Action Group webhook URL configuration (e.g., [https://your-api.com/api/webhooks/azure-alert?code=YourSuperSecretToken123](https://your-api.com/api/webhooks/azure-alert?code=YourSuperSecretToken123)), and validate it in your controller:
C#
[HttpPost("azure-alert")]
public IActionResult ReceiveAzureAlert([FromQuery] string code, [FromBody] AzureAlertPayload payload)
{
const string expectedToken = "YourSuperSecretToken123";
if (string.IsNullOrEmpty(code) || !code.Equals(expectedToken))
{
_logger.LogWarning("Unauthorized webhook access attempt detected.");
return Unauthorized(new { message = "Invalid or missing authorization token." });
}
// Process valid alert...
return Ok(new { status = "Success" });
}
2. IP Restriction
Configure your reverse proxy (such as Nginx, Apache, or Azure App Service IP restrictions) to whitelist only incoming requests originating from Azure Monitor's official service tag IP address ranges.
Summary
By building a custom webhook receiver in ASP.NET Core, you complete the loop between cloud observability and automated action. Your application can now ingest Azure Monitor alerts in real time, parse them reliably using strongly-typed DTOs, and execute internal business logic or remediation workflows instantly.

Join the conversation! Your thoughts help the community grow.