尽管较新版本的 HL7.Fhir NuGet 包(当前处于测试阶段)将携带额外的 [DataContract] 和 [DataMember] 属性,从而防止此类错误,但标准 .NET DataContract 序列化程序将无法序列化 -将 POCO 内存为正确的 FHIR XML 和 Json 表示形式。 FHIR 序列化对于如何使用 XML 和 json 有特定的规则,使用 DataContract 序列化程序的(有限)可能性来配置这即使不是不可能,也是很困难的。
但是,也没有必要为每个调用调用 FhirSerializer,如代码片段中所示(事实上,这将是 WebApi 反模式)。例如,我们的 FHIR 服务器(位于http://spark.furore.com/fhir)基于 WebApi 并使用自定义 MediaTypeFormatter 来处理此问题。为了体验一下它的样子,我们创建了两个格式化程序,一个用于 json,一个用于 xml:
public class JsonFhirFormatter : MediaTypeFormatter
{
public JsonFhirFormatter() : base()
{
foreach (var mediaType in ContentType.JSON_CONTENT_HEADERS)
SupportedMediaTypes.Add(new MediaTypeHeaderValue(mediaType));
}
}
这告诉框架此格式化程序将采用 ContentType.JSON_CONTENT_HEADERS 中的任何格式(即 application/json 和一些常见变体),并且能够解析和读取 FHIR ModelTypes:
public override bool CanReadType(Type type)
{
return type == typeof(ResourceEntry) || type == typeof(Bundle) || (type == typeof(TagList));
}
public override bool CanWriteType(Type type)
{
return type == typeof(ResourceEntry) || type == typeof(Bundle) || (type == typeof(TagList)) || type == typeof(OperationOutcome);
}
最后,您必须重写 ReadFromStreamAsync 和 WriteToStreamAsync 方法:
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
{
// Some code left out...
XmlWriter writer = new XmlTextWriter(writeStream, Encoding.UTF8);
if (type == typeof(ResourceEntry))
{
ResourceEntry entry = (ResourceEntry)value;
FhirSerializer.SerializeResource(entry.Resource, writer);
content.Headers.SetFhirTags(entry.Tags);
}
现在,一旦您完成了此操作,您的控制器就可以简单地执行以下操作:
[HttpGet, Route("metadata")]
public ResourceEntry Metadata()
{
return service.Conformance();
}
[HttpOptions, Route("")]
public ResourceEntry Options()
{
return service.Conformance();
}
请注意,我们的服务器不使用资源作为控制器中的参数和返回值。资源不允许您捕获重要的元数据(如 ID、版本 ID、上次修改日期等)。通过在我的控制器中使用 ResourceEntry,此数据可以与资源数据一起传递,并且 WebApi 框架可以将此元数据绑定到适当的 HTTP 标头。