What's new and changed in the FHIR .NET API 2.0?
Over six years ago, we released the first version of the FHIR .NET API. It has grown to a sturdy 1.300 classes and over 300.000 lines of code (admittedly, partly generated) in that time. Even while growing, we have decently managed to keep our library compile-time compatible, making sure that a new version would always compile against your existing code. Of course, we have encountered a number of bigger, breaking changes during that period. Version 2.0 of the API is introducing a first set of some of the most-wanted issues from that list. Over the past months we have worked hard to get them ready, in a way that will hopefully introduce the benefits, without too many breaking changes.
So, what is new? The next sections will give you an overview of the biggest changes, more details can be found in https://github.com/FirelyTeam/fhir-net-api/wiki/Breaking-changes-in-2.0
A new FhirClient
FhirClient is one of the most-used (and oldest) parts of the library, and was still using Microsoft's
HttpWebResponse as the underlying technology. These classes have been superceded quite a while ago, and has been upgraded to use Microsoft's newer
HttpClient, providing more flexibility to customize and manipulate the HTTP traffic. It also has better support for newer TLS versions. A big thanks has to go to our community members Brad Barnich and Devereux Henley who provided most of the code to get this task done.
We have made this a drop-in replacement: when you are using the
FhirClient, you will be using this new implementation in 2.0. The interface has changed only minimally, and if you run into problems, the older client based on
HttpWebRequest is still available, but is now called LegacyFhirClient (marked
[Obsolete]). It is strongly recommended to use the new FhirClient implementation!
More common code across FHIR versions
Initially, when HL7 released the DSTU2 version of FHIR, so much of the datamodels and functionality had changed that we decided to ship two separate versions of the .NET FHIR API, both being more or less identical copies but each supporting only one version. This process has continued for STU3 and R4, but as these more recent versions of FHIR have more and more in common, we have started to identify and isolate common parts. A year ago, we split off common code from the
fhir-net-api repo into the submodule repo called
fhir-net-common. In 2.0, thanks to being able to make some minor breaking changes to the API and dropping DSTU2 support, we have managed to move some of the most-used common base resources to the common library:
Element are just a few I should mention in this respect. This means that the POCO classes representing FHIR data (like
Patient), now share a common base class across all FHIR versions. This makes it much easier to write applications supporting multiple FHIR versions. It is not as easy yet as we would wish, but we have taken a major step.
Also, we have backported the type hierarchy introduced in the early drops of R5 into the STU3 and R4 versions of the API, so all these versions now share the same backbone of abstract base classes.
A large part of the I/O activities of the API is caused by validation and the parsers/serializers trying to reach out to the conformance resources (FHIR's metadata) supplied by the FHIR specification. These are abstracted behind resolvers, which some of you might have created specific implementations for. Until now, these were synchronous. To enable better scalability, we are introducing
IAsyncResourceResolver, and all functionality in the API using resolvers will now accept either sync or async resolvers.
Support for FhirPath Normative
We have had support for FhirPath (http://hl7.org/fhirpath/) for quite a while, but this was based on the pre-normative versions of the language shipped with FHIR DSTU2, and adapted slightly in STU3. HL7 has recently published the final "normative" version of FhirPath, which is not only used in FHIR (mostly for formulating business rules in StructureDefinition/profile validation) but also in CQL.
The normative version has an expanded set of math and string manipulation operations, introduces quantities, better handling of date/time precision. The normative version does introduce a few breaking changes and so is not fully compatible with the pre-normative version. You will find, however, that most of the FhirPath statements you have used in DSTU2/STU3 will still work.
2.0 does not yet support some of the more experimental parts of FhirPath Normative, specifically:
- Quantity comparisons with different units and quantity math
- Date/time math
- The new
We will be adding these features gradually over the next months.
Clean-up of the API
There is a whole host of smaller changes, mostly removal of methods that have been marked as
[Obsolete] for a while. Also, we removed some almost empty namespaces, which were created by accident in the previous versions. Most of the time, just removing the now incorrect
using statement would suffice to make things build again.
Better support for non-FHIR models
With FHIR's grown popularity, its technologies (like the serialization, type system and conformance resources) have been used to support non-FHIR models like CDA. The scope of some of FHIR's primary DSLs (mainly FhirPath and the mapping language) have been broadened to be used within CQL and even map non-FHIR models to non-FHIR models. To keep up with this expanded use, we have started to make parts of the API more generic, and remove code that assumes it will only be used in a pure FHIR context. These changes will take quite a while to materialize, but the most visible step in the 2.0 release is the introduction of a shared set of primitive datatypes, called the "system types", which are shared beteen FHIR, CQL, FhirPath and the Mapping Language. These types express a shared notion of equality, order and a shared set of (mathematical) operations that can be performed on them. Most users will not be influenced by these changes as these are pretty much internal, and will only become visible in subsequent versions of the API in the non-POCO parts of the FHIR .NET API, most notably if you use
IStructureDefinitionSummary or the
2.0 does not support DSTU2
There is no DSTU2 version of the 2.0 library. We have seen the use of DSTU2 decline sharply over the past year. As well, there were some significant changes going from DSTU2 to STU3 (and later), and trying to support DSTU2 would mean we could not have introduced some of the improvements in this version. Finally, this is a volunteer project, and there's a limit on how much time we can spend supporting older versions.
Today, we are releasing 2.0-beta2. We are doing this for several reasons: we wanted to bring you an early release, since we know many of you want to try out the new
FhirClient and the asynchronous resolvers. But we also love to hear which breaking changes cause you trouble, so we can improve matters before we publish the final 2.0 release. So, please, be our guest, try out this new version and let us know what does and does not work!
Where to get it?
The new 2.0 beta release is available on NuGet (look for Hl7.Fhir.Core and Hl7.Fhir.Specification) but make sure you select "Include prerelease" - otherwise it will just present you the 1.x versions. If you want to compile it yourself, make sure you checkout either the
develop-r4 branch (https://github.com/FirelyTeam/fhir-net-api/tree/develop-stu3) and the
develop branch of the submodule repository (https://github.com/FirelyTeam/fhir-net-common/tree/develop).