Azure DevOps Server Health Dashboard with WinRM and Blazor

I built this to stop checking servers by hand and to show a single view of IIS, scripts, and server health from a lower-environment reporting database.

What I Needed to Solve

The goal was simple: run a scheduled health check from Azure DevOps, validate Windows servers through WinRM, save the result into a reporting database, and show the latest state in a Blazor dashboard.

Why This Was Worth Building

How I Structured It

Data Panel
Reference table for quick scanning and comparison.
Reference Live Status
LayerResponsibility
Azure DevOps pipelineSchedules checks and runs the validation script
PowerShell scriptConnects over WinRM, runs the checks, writes JSON
Reporting APIStores snapshots into a lower-environment database
Blazor dashboardReads the reporting data and renders the operator view

Demo Dashboard Preview

This small preview shows the shape of the dashboard I built. The real UI reads from the reporting DB, but this captures the summary cards and server grid clearly.

Total Servers

12
Across QA, UAT, and PROD

Passed

9
Healthy on latest run

Warning

2
Needs attention soon

Failed

1
WinRM or IIS check failed
Health Snapshot
Current server checks with status chips.
Live Healthy Watch
Server Environment Last Check Status
APP-SRV-01 QA 2026-06-05 10:00 UTC Passed
WEB-SRV-02 UAT 2026-06-05 10:00 UTC Warning
IIS-PROD-03 PROD 2026-06-05 10:00 UTC Failed

PowerShell Validation Shape

The script ran server-by-server, returned JSON, and stayed read-only unless I intentionally added a remedial step later.

param(
    [string]$ServerListFile,
    [string]$OutputDir
)

$servers = Get-Content $ServerListFile | ConvertFrom-Json
foreach ($server in $servers) {
    $result = [pscustomobject]@{
        server = $server.name
        environment = $server.environment
        checkedAtUtc = (Get-Date).ToUniversalTime().ToString("o")
        checks = @(
            [pscustomobject]@{ name = "Ping"; status = "Passed"; message = "Reachable" },
            [pscustomobject]@{ name = "IIS"; status = "Passed"; message = "Site started" }
        )
    }

    $result | ConvertTo-Json -Depth 8 | Set-Content (Join-Path $OutputDir "$($server.name).json")
}

Blazor Dashboard Shape

The dashboard reads the latest snapshot, shows the summary cards, and renders each server with its check breakdown.

@page "/health-dashboard"
@inject HttpClient Http

@if (_model is null)
{
    

Loading...

} else {

Server Health Dashboard

Last refresh: @_lastRefreshText

Data Panel
Reference table for quick scanning and comparison.
Reference Live Status
@foreach (var row in _model.Rows) { }
Server Environment Status
@row.Server @row.Environment @row.Status
}

Security Controls I Kept

What I Would Show Next

The next useful step is to wire the reporting API and the dashboard component to the snapshot DB so the preview becomes live data.

© 2026 Anup Kumar Chandrakumaran