View on GitHub

Fhir-net-api

The official .NET API for HL7 FHIR

Download this project as a .zip file Download this project as a tar.gz file

Doing basic CRUD with FhirClient

A FhirClient named client has been setup in the previous topic, now let's do something with it.

Create a new Resource

Assume we have created a new Patient and now we want to ask the server to store it for us. This is done using Create():

var pat = new Patient() { /* set up data */ };
var patEntry = client.Create(pat);

As you'd probably expect, this operation will throw an Exception when things go wrong, in most cases a FhirOperationException. This exception has an Outcome property that contains an OperationOutcome, and which you may inspect to find out more information about why the operation failed. Most FHIR servers will return a human-readable error description in the OperationOutcome to help you out.

If the operation was successful, it will return an instance of a ResourceEntry<Patient>. ResourceEntries are classes that contain both the Resource's data and its metadata, like its server-assigned id, version number, last modified date and others. All that's important to realize here is that Create does not return an instance of Patient, but a ResourceEntry<T>. In fact, this ResourceEntry will just have the Patient's newly assigned metadata, not even a copy of the data you just posted to the server. Since you already have the Patient's data at hand, the server will, by default, not bother to return a copy of the data to save bandwidth.

In short, although the ResourceEntry's Id and LastUpdated and other metadata properties will be set, its Resource property will still be null. To get a copy of the resource as it was stored on the server, pass true as the refresh parameter to the Create operation.

Refreshing data

Whenever you have held a Resource for some time, its data may have changed on the server because of changes made by others. At any time, you can refresh your local copy of the data by using the Refresh call, passing it the ResourceEntry as returned by a previous Read or Create:

var newEntry = client.Refresh(oldEntry);

This call will go to the server and fetch the latest version and metadata of the Resource as pointed to by the Id property in the ResourceEntry passed as the parameter.

Getting an existing Resource

To read the data for a given Resource instance from a server, you'll need its web address (url). You may have previously stored this reference, or you have found its address in a ResourceReference (e.g. Observation.subject.reference).

The Read operation on the FhirClient has two overloads to cover both cases. Furthermore, it accepts both relative paths and absolute paths (as long as they are within the endpoint passed to the constructor of the FhirClient). As with the other operations, Read returns a typed ResourceEntry rather than the Resource itself:

// Read the current version of a Resource
var location = new Uri("http://spark.furore.com/fhir/Patient/31");
var patEntryA = client.Read<Patient>(location);
var patEntryA = client.Read<Patient>("Patient/31");

// Read a specific version of a Resource
var locationB = new Uri("http://spark.furore.com/fhir/Patient/32/_history/4");
var patEntryB = client.Read<Patient>(locationB);
var patEntryB = client.Read<Patient>("Patient/32/_history/4");

Read only takes urls as parameters, so if you have the resource name and its Id as distinct data variables, use ResourceIdentity:

var patEntryA = client.Read<Patient>(ResourceIdentity.Build("Patient","31"));

Note that Read can be used to get the most recent version of a Resource as well as a specific version, and thus covers the two 'logical' REST operations read and vread.

Updating a Resource

Once you have retrieved a Resource, you may edit its contents and send it back to the server. This is done using the Update operation. It takes the ResourceEntry previously retrieved as a parameter:

var patEntry = client.Read<Patient>(location);
// Add a name to the patient, and update
patEntry.Resource.Name.Add(HumanName.ForFamily("Kramer").WithGiven("Ewout"));
client.Update(patEntry);

There's always a chance that between retrieving the resource and sending an update, someone else has updated the resource as well. Servers supporting version-aware updates may refuse your update in this case and return a HTTP status code 409 (Conflict), which causes the Update operation to throw a FhirOperationException with the same status code.

Deleting a Resource

The Delete operation on the FhirClient deletes a resource from the server. It is up to the server to decide whether the resource is actually removed from storage, or whether previous versions are still available for retrieval. The Delete operation has multiple overloads to allow you to delete based on an url or a ResourceEntry:

var location = new Uri("http://spark.furore.com/fhir/Patient/34");
client.Delete(location);

// You may also delete based on an existing ResourceEntry
client.Delete(patEntry);

The Delete operation will fail and throw a FhirOperationException if the Resource was already deleted or if the Resource did not exist before deletion.

Note that sending an update to a Resource after it has been deleted is not considered an error and may effectively "undelete" it.

Further reading