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
The FhirClient
is one of the most-used (and oldest) parts of the library, and was still using Microsoft's HttpWebRequest
and 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!
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: Resource
, DataType
and 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.
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
- Reflection
- The new
aggregate
function.
We will be adding these features gradually over the next months.
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.
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 ITypedElement
, IStructureDefinitionSummary
or the ClassMapping
classes.
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!
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-stu3
or 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).