尽管 HL7.Fhir NuGet 包的较新版本(目前处于测试阶段)将带有额外的 [DataContract] 和 [DataMember] 属性,从而防止此类错误,但标准 .NET DataContract 序列化程序将无法序列化 in-内存 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、version-id、上次修改日期等)。通过在我的控制器中使用 ResourceEntry,可以将此数据与资源数据一起传递,并且 WebApi 框架可以将此元数据绑定到适当的 HTTP 标头。