HealthData.Interop.Fhir

A runnable reference implementation for HL7 FHIR R4 interoperability on .NET, built on the Firely .NET SDK β€” with working examples you can read, run, and adapt: FHIR R4 client utilities, HIPAA Security Rule–oriented security examples (RBAC, consent, audit, PHI masking), and US Core profile checks.

.NET 8 library / .NET 10 samples FHIR R4 HIPAA Security Rule examples US Core profile checks v1.4.3
Rong(Rex) Fan

By Rong (Rex) Fan

πŸ“’ Free Resource

Building FHIR interoperability? I made a free checklist of the 12 pitfalls teams hit before Cures Act certification.

πŸ₯ More Healthcare IT Projects by the Author

Two independent healthcare IT projects built by the author. They are not built on top of this library β€” they simply live in the same healthcare interoperability space.

Installation

Install the HealthData.Interop.Fhir NuGet package into your .NET project:

πŸ“¦ Download on NuGet.org
# Via .NET CLI
dotnet add package HealthData.Interop.Fhir

# Via Package Manager Console
Install-Package HealthData.Interop.Fhir

# Via Paket
paket add HealthData.Interop.Fhir
Note: This package targets .NET 8.0 LTS. Compatible with .NET 9, .NET 10 and later versions due to forward compatibility of the .NET platform.

Quick Start

Get up and running with FHIR R4 client operations:

using HealthDataInteropSharedLibrary.BasicClient;
using HealthDataInteropSharedLibrary.ResourceValidator;

var client = new FhirBasicService("https://your-fhir-server/fhir");

// Search patients by name
var results = await client.SearchPatientsByNameAsync("Doe");
foreach (var patient in results)
{
    Console.WriteLine($"Patient: {FhirBasicService.FormatPatientName(patient)}");
}

// Create a patient
var created = await client.CreatePatientAsync(
    new[] { "John" }, "Doe", "male", "1985-01-15", "MRN-1234");

// Validate a Patient resource against the R4 specification
var validator = new ResourceValidationService();
if (results.Count > 0)
{
    bool valid = validator.Validate(results[0]);
    Console.WriteLine(valid ? "Valid against FHIR R4." : "Validation found issues.");
}

What This Project Demonstrates

This repository is an application-layer toolkit and reference implementation for HL7 FHIR R4 interoperability on .NET, built on the Firely .NET SDK. It does not replace a FHIR server, and it does not by itself provide certified HIPAA or ONC compliance. It is a set of working patterns you can read, run, and adapt:

It is intended as a reference implementation and educational resource β€” see the License section below.

Modules & What They Demonstrate

Each numbered module is a small console app exercising one scenario:

ModuleWhat it doesWhat it demonstrates
01 Basic FHIR Client Patient create + search against a FHIR R4 server The basic pattern: point a FhirClient at a server, create and search Patient resources.
02 Advanced Query Chained search; _include/_revinclude Fetching related resources in a single query instead of multiple round-trips.
03 FHIR Resource Validation Firely SDK validation + US Core profile check Validation against the FHIR R4 specification (works offline), and checking that a Patient declares a US Core profile URI in Meta.Profile β€” profile-declaration checking, not full IG conformance.
04 Data Mapping / ETL CSV β†’ FHIR Patient mapping pipeline Idempotent upserts: search by business identifier first, then Conditional PUT (ETag) or create, batched in a transaction bundle β€” re-running updates instead of duplicating.
05 SMART on FHIR OAuth2/OIDC client-credentials + SMART-style ETL Token acquisition with caching/refresh, an authenticated FhirClient, and scope-based access patterns (openid profile patient/*.read).
06 AI-Assisted Data Mapping Local LLM (Ollama) record normalization A local model normalizes messy records into a small DTO; deterministic guardrails reject invalid output. Designed for local inference β€” data does not need to go to a cloud LLM.
07 HIPAA Technical Safeguards Demo RBAC, consent, audit, PHI masking Walks one simulated PHI access request through RBAC β†’ consent (purpose of use) β†’ audit log, with PHI-masked console output. A technical-safeguards demo, not a compliance product.
08 Data Drift Detector Read-only reconciliation, legacy source vs. FHIR copy Field-by-field comparison with explicit outcomes: in sync / field-level drift / missing on server. Detection only β€” it never writes.

API Reference

BasicClient.FhirBasicService

// Constructor: FHIR server base URL
var service = new FhirBasicService("https://your-fhir-server/fhir");

// Key methods:
var patients = await service.SearchPatientsByNameAsync("Doe");
var created  = await service.CreatePatientAsync(
    new[] { "John" }, "Doe", "male", "1985-01-15", "MRN-1234");
Console.WriteLine(FhirBasicService.FormatPatientName(patients[0]));

ResourceValidator.ResourceValidationService

var validator = new ResourceValidationService();
bool isValid = validator.Validate(patient);
var issues = validator.GetValidationIssues(patient);

ResourceValidator.UsCoreConformanceChecker

// Check if a Patient resource declares a US Core profile
var result = UsCoreConformanceChecker.CheckPatientConformance(patient);
Console.WriteLine(result.IsUsCoreConformant); // true or false

// Ensure Patient has a US Core profile in Meta
bool added = UsCoreConformanceChecker.EnsureUsCoreProfile(patient);

Compliance.HipaaComplianceOrchestrator

// RBAC PHI access check (8 roles) β€” synchronous, returns bool
var orchestrator = new HipaaComplianceOrchestrator();
bool allowed = orchestrator.ExecutePhiAccessRequest(
    userId: "u-1001",
    role: FhirUserRole.Physician,
    ipAddress: "10.0.0.5",
    patientId: "123",
    accessPurpose: "Clinical review");

// PHI encryption service (AES-256-GCM; supply your own 32-byte key)
var key = new byte[32]; // key management is your responsibility
var phi = new PhiEncryptionService(key);
var (ciphertext, nonce, tag) = phi.Encrypt(sensitiveData);
var plaintext = phi.Decrypt(ciphertext, nonce, tag);

// Audit log
AuditLog.Record(
    userId: "u-1001", role: "Physician", ipAddress: "10.0.0.5",
    resourceType: "Patient", resourceId: "123", action: "READ");

Etl.EtlPipelineService

// CSV to FHIR Patient mapping pipeline
var mapper = new FhirPatientMapper(addTestDataTag: true, testNameMarkers: true);
var service = new EtlPipelineService(fhirClient, mapper);
var (created, updated) = await service.RunAsync("data/legacy_patients.csv");

AIDataValidator.AiValidatorService

// Requires Ollama running locally with the llama3 model.
// The AI provider is injected as a plain Func<string, Task<string>>,
// so you can point it at any local model endpoint.
var validator = new AiValidatorService(prompt => OllamaChatAsync(prompt));
var patient = await validator.ProcessRawRecordAsync("Mmale, Jhon Doe, 1990-05-14");

Security Notice

Development vs. production: TLS certificate validation is strict by default on all FHIR client connections. A development-only bypass exists for local self-signed test setups and is OFF by default β€” enable it only for local development by setting the environment variable HEALTHDATA_INSECURE_SKIP_TLS=1. It must never be enabled in production (conflicts with HIPAA Β§164.312(e)(1) transmission-security requirements). Application logging is PHI-masked: SSN, patient name, DOB, phone and email are redacted before reaching the log sink. Always use valid certificates and enforce TLS 1.2+ for all FHIR server connections.

License & Disclaimer

This project is licensed under the MIT License.

NO WARRANTY / NO MAINTENANCE:

This project is provided as a reference implementation and educational resource. The author provides NO FUTURE MAINTENANCE, bug fixes, feature updates, or support. You are expected to use this code entirely at your own risk.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY ARISING FROM THE USE OF THIS SOFTWARE.

πŸ™Œ Support this work

If this work is helpful to you, feel free to send a small gift β€” it helps support my work and keep the project maintained.