Welcome to the second post of this blog series where I show you how to create simple custom EHR to HL7 FHIR* integration using the latest Microsoft tech stack. In the first article, I introduced the HL7 FHIR standard and the .NET 5 framework. In this second post, I will share how you can integrate Patients into your solution. In the final part, I will describe how to integrate Patient Observations (blood tests).
HL7 FHIR PATIENTS
FHIR includes many different Resources, one of which is the Patient Resource. Official documentation states that this Resource covers data about patients (and animals) involved in a wide range of health-related activities, including:
- Curative activities
- Psychiatric care
- Social services
- Pregnancy care
- Nursing and assisted living
- Dietary services
- Tracking of personal health and exercise data
The data in the Resource covers the “who” information about the patient: its attributes are focused on the demographic information necessary to support the administrative, financial, and logistic procedures. A patient record is generally created and maintained by each organisation who provides care for a patient. A patient or animal receiving care at multiple organisations may therefore have their information present in multiple Patient Resources.
Let’s start with the implementation. I assume that you already have some development experience, so I will not go into detail on how to use Visual Studio 2019 and NuGet Packages.
But first – architecture. I created three new projects:
- Hl7.Fhir.Common.Contracts – class library
- Hl7.Fhir.Common.Core – class library
- Hl7.Fhir.OpenAPI – web application
The Hl7.Fhir.Common.Contracts library contains mostly data models and converters which are used across the solution.
The Hl7.Fhir.Common.Core library contains common services, attributes, extensions, etc.
Hl7.Fhir.OpenAPI – this is the start-up web API project which implements OpenAPI specifications with the following features as described by Swagger: The OpenAPI Specification (OAS) defines a standard, programming-language-agnostic interface description for HTTP APIs. This allows both humans and computers to discover and understand the capabilities of a service without requiring access to source code, additional documentation, or the inspection of network traffic. When properly defined via OpenAPI, a consumer can understand and interact with the remote service with a minimal amount of implementation logic. Similar to what interface descriptions have done for lower-level programming, the OpenAPI specification removes guesswork when calling a service.
The final solution looks like this:
The web API is configured to use the public FHIR server UHN_HAPI Server (R4), which is regularly purged and reloaded with fixed test data. Of course, you can use a different FHIR server from the list of FHIR test servers. For logging, I’ve used Serilog, which is configured with a Serilog configuration section in the appsettings.json file:
The EHR system communicates with OpenAPI through different controllers/endpoints. For a Patient, there are several endpoints available. Using Swagger UI “allows anyone – be it your development team or your end consumers – to visualize and interact with the API’s resources without having any of the implementation logic in place. It’s automatically generated from your OpenAPI Specification, with the visual documentation making it easy for back end implementation and client side consumption.” Pretty cool, huh!
CREATE A NEW PATIENT
Let’s go through the typical data flow and create a new Patient. For this purpose, I will use the api/Patient/Create endpoint and send the following PatientDto in a body request. The result is a new Patient being created:
DIG INTO THE CODE
Now, let’s go into the details. The PatientDto model was transferred to the /api/Patient/Create endpoint. After the model validation, PatientService is called using the CreatePatientAsync method.
In the first step, the CreatePatientAsync method converts PatientDto data into an FHIR Patient resource, and in the next step, it validates a new Patient resource. If the validation was successful, then FhirClient creates a Patient on the FHIR server and returns it with a new ID.
MAPPING PATIENTDTO TO THE FHIR PATIENT RESOURCE
A crucial part of our integration is mapping the EHR model to the FHIR resource. In our case, the EHR model is PatientDto (DTO is Data Transfer Object), which has to be converted into the FHIR Patient resource. This is done using a model converter:
PatientController supports most common endpoints, and you can use it to get a Patient by identifier or by resource ID, you can update an existing Patient, and even import a list of Patients from a CSV file (an example CSV file is included in the Resources/Files folder of this solution).
In the next post, I will present how you can integrate the FHIR Observation resource.
Find example source code for this series on Endava’s GitHub.
TAGS, TECHNOLOGIES AND SOURCES
Swagger – interactive API documentation
API-Docs – friendly API documentation
Serilog – flexible, structured logger
FluentValidation – a popular .NET library for building strongly-typed validation rules
Firely .NET SDK – the official HL7 FHIR SDK in .NET
Extra documentation for FhirClient
HL7 FHIR Restful API specification
Firely.NET SDK FHIR Community
List of FHIR test servers
* HL7® and FHIR® are the registered trademarks of Health Level Seven International.