Emergency dispatch · legacy modernization

Making a large emergency-service platform workable under pressure.

A government emergency-dispatch platform where the important work was extending and modernizing a large legacy system while the project was already under delivery pressure.

What it was

The Unified Contact Center Platform was intended to bring several Latvian emergency services into a shared operational environment. The practical goal was to reduce handoff delay between separate call centers and give operators, managers, and dispatched crews a common view of incidents, resources, roles, reports, and related integrations.

The domain was meaningful: emergency calls, dispatch decisions, crews, shifts, equipment, response-time tracking, video integrations, and registry data. The engineering reality was less clean: the team started from a stripped older project and had to deliver under fixed public-sector constraints.

Starting point

The inherited system was a large .NET Framework application: roughly hundreds of projects across several solutions, a WPF desktop client, WCF modules hosted in IIS, old-style project files, packages.config, binding redirects, Prism/MVVM, CefSharp, SQL Server, ADO.NET-based persistence, and a database layer heavy with stored procedures, views, triggers, and user-defined types.

The project had no meaningful automated test base. Local setup was manual enough that a fresh checkout was not always the shortest way to a working development environment. UI work often meant editing WPF bindings by judgement, launching the application, and checking behavior manually.

My role

My work crossed backend, desktop-client, database-adjacent, build, and delivery concerns. In this project “full stack” meant application full stack: not only server code, but also WPF UI, scenario forms, integration support, release preparation, and practical modernization inside the system that already existed.

  • Modernized the working baseline from older .NET Framework/C# and packages.config toward .NET Framework 4.8.3, C# 9, and PackageReference.
  • Extended the JSON-driven call scenario engine and generated schemas so call-plan authors could get IntelliSense while editing scenario definitions.
  • Built a .NET task runner payload that imported Latvian address data from PostgreSQL into MS SQL Server with A/B table slots and minimal service interruption.
  • Created Swagger documentation support for WCF endpoints by reflecting endpoint metadata and generating stubs Swagger could consume.
  • Explored a large .NET 6 migration of the tightly-coupled client/server system; the application ran locally, while the delivery path still had unresolved MSIX issues.
  • Participated in release preparation and mentored newer developers while working inside a delivery-heavy government project.

Modernization

One major thread was improving the development baseline. I updated the project toward .NET Framework 4.8.3 and C# 9, converted many projects from packages.config to PackageReference, consolidated dependency versions where possible, and dealt with the binding redirect fallout that comes with that kind of migration.

I also explored a wider migration to modern .NET. The last attempt got the tightly coupled client/server application running locally on .NET 6, but delivery remained blocked by unresolved ClickOnce-to-MSIX problems and application assumptions that did not fit the MSIX sandbox model. It was a useful technical spike, not something I would present as a completed production migration.

Scenario engine

Operators worked through call scenarios where selecting an incident type dynamically changed the form and next questions. The behavior was driven by JSON definitions interpreted by an engine. I extended that engine with additional rules and reusable form pieces, and worked on the definitions needed for many call-plan variations.

To make those definitions safer to write, I built a JSON schema generator so scenario authors could get schema validation and editor IntelliSense instead of editing large dynamic JSON files blindly.

Endpoint docs

The platform exposed WCF endpoints, but they did not naturally fit the Swagger tooling people expected from newer HTTP APIs. I built support around that gap: reflecting endpoint information, generating stub classes, and feeding those stubs into Swagger so the API surface could be inspected more easily.

This was practical system repair: making an older service style more understandable without first rewriting the service boundary.

Address import

Another substantial piece was a task-runner payload for address data. It read Latvian address tables from a local PostgreSQL replica, compared them with the platform's SQL Server data, calculated differences, wrote updates into an inactive slot, and then switched the active alias so the service could continue with minimal interruption.

This was built as a separate .NET task payload, using Dapper for database access and running only when invoked. Memory usage and peak processing behavior mattered because the task handled large data sets compared with the normal request path.

What it proves

UCCP is not a clean-architecture trophy. It proves something more useful in many real companies: I can understand a large inherited system, improve the parts that are possible to improve, extend dynamic business behavior, work around delivery constraints, and still keep enough judgement to separate a successful spike from a production-ready migration.