Stream: dotnet
Topic: Dotnet APi
Francisco Nolla (Oct 08 2019 at 18:00):
Hi,
I am getting this error in dotnet core 2.2. I know that the issue is that it doesn't know how to handle the input of when the controller maps to that resource. I have tried adding an input formatter but haven't been able to get it to work. I am wondering if anyone can help with this issue.
public IActionResult Post([FromBody] PractitionerRole pr) { // some code }
Could not create an instance of type Hl7.Fhir.Model.Element. Type is an interface or abstract class and cannot be instantiated
Brian Postlethwaite (Oct 08 2019 at 23:09):
You can take a peek at how its done in the fhir-net-web-api project
https://github.com/brianpos/fhir-net-web-api
If you want to use it, there is a demo that uses the file system to simulate storage.
Francisco Nolla (Oct 09 2019 at 02:54):
Yeah, im not trying to implement a fhir api. I'm trying to take fhir objects in my api and use them for other purposes so a route like the one I posted has this difficulty. I implemented the formatter for input and output so that it parses fhir correctly. the only problem now that I have is nesting of types.
Say I have a route that has this class below as the [FromBody] parameter in the function above. My formatters are not working because that type is not fhir. the nested type however is. So i'm having a hard time understanding how to get the formatter to understand nested properties.
public class SomeParentInput
{
[Required]
public string PractitionerReference { get; set; }
[Required]
public Hl7.Fhir.Model.PractitionerRole PractitionerRole { get; set; }
}
Here are my formatters. They work when the payload is just a PractitionerRole or any fhir type. But when it is nested this will fail because the canreadtype is false because it is not of type resource.
```using System;
using System.Buffers;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Hl7.Fhir.Model;
using Hl7.Fhir.Rest;
using Hl7.Fhir.Serialization;
using Hl7.Fhir.Utility;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.AspNetCore.Mvc.Formatters.Json.Internal;
using Microsoft.Net.Http.Headers;
using Newtonsoft.Json;
using Task = System.Threading.Tasks.Task;
namespace Configurations.Formatters
{
public class CiscoFormatter : TextInputFormatter
{
public CiscoFormatter()
{
foreach (var mediaType in ContentType.JSON_CONTENT_HEADERS)
SupportedMediaTypes.Add(new MediaTypeHeaderValue(mediaType));
SupportedEncodings.Add(Encoding.Default);
SupportedEncodings.Add(Encoding.UTF8);
SupportedEncodings.Add(UTF8EncodingWithoutBOM);
}
protected override bool CanReadType(Type type)
{
bool can = typeof(Resource).IsAssignableFrom(type);
return can;
}
public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var request = context.HttpContext.Request; using (var reader = new StreamReader(request.Body, encoding)) using (var jsonReader = new JsonTextReader(reader)) { var parser = new FhirJsonParser() { Settings = { AcceptUnknownMembers = true, } }; var resource = parser.Parse<Resource>(jsonReader); return await InputFormatterResult.SuccessAsync(resource); } } } public class CiscoOutputFormatter : TextOutputFormatter { public CiscoOutputFormatter() { foreach (var mediaType in ContentType.JSON_CONTENT_HEADERS) SupportedMediaTypes.Add(new MediaTypeHeaderValue(mediaType)); SupportedEncodings.Add(Encoding.Default); SupportedEncodings.Add(Encoding.UTF8); } protected override bool CanWriteType(Type type) { if (typeof(Resource).IsAssignableFrom(type) || typeof(IEnumerable<Resource>).IsAssignableFrom(type)) { return base.CanWriteType(type); } return false; } public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding) { var response = context.HttpContext.Response; var serializer = new FhirJsonSerializer() { Settings = { Pretty = true } }; using (StreamWriter writer = new StreamWriter(context.HttpContext.Response.Body)) { JsonTextWriter jsonwriter = (JsonTextWriter)SerializationUtil.CreateJsonTextWriter(writer); // This will use the BetterJsonWriter which handles precision correctly using (jsonwriter) { jsonwriter.ArrayPool = new JsonArrayPool<char>(ArrayPool<char>.Shared); jsonwriter.Formatting = Formatting.Indented; // lets make it pretty SummaryType st = SummaryType.False; if (context.ObjectType == typeof(OperationOutcome)) { // We will only honor the summary type during serialization of the outcome // if the resource wasn't a stored OpOutcome we are returning OperationOutcome resource = (OperationOutcome)context.Object; if (string.IsNullOrEmpty(resource.Id) && resource.HasAnnotation<SummaryType>()) st = resource.Annotation<SummaryType>(); serializer.Serialize(resource, jsonwriter, st); } else if (typeof(Resource).IsAssignableFrom(context.ObjectType)) { if (context.Object != null) { Resource r = context.Object as Resource; if (r.HasAnnotation<SummaryType>()) st = r.Annotation<SummaryType>(); serializer.Serialize(r, jsonwriter, st); } } return writer.FlushAsync(); } } } }
}```
George Kustas (Dec 16 2019 at 16:28):
I'm looking to accept R4 FHIR data in my .Net Core Web Service. Is this project still useful for me, or are there newer examples or other means of deserializing FHIR Resources in .Net Core?
I'm using the latest Hl7.Fhir POCO. Up to now, I've just been defining the FHIR Resources as simple .Net "object" types, and parsing them after the fact. I would ultimately like to define the resource as Hl7.Fhir.Model.Resource, and have .Net MVC deserialize it for me (via annotations or custom deserializer if necessary).
Current model:
public sealed class Notification { [JsonProperty(PropertyName = "timestamp")] public DateTime Timestamp { get; set; } [JsonProperty(PropertyName = "id")] public string Id { get; set; } [JsonProperty(PropertyName = "event")] public NotificationEvent Event { get; set; } } public sealed class NotificationEvent : ModelBase { [JsonProperty(PropertyName = "hub.topic")] public string Topic { get; set; } [JsonProperty(PropertyName = "hub.event")] public string HubEvent { get; set; } [JsonProperty(PropertyName = "context")] public List<Context> Contexts { get; set; } } public sealed class Context { [JsonProperty(PropertyName = "key")] public string Key { get; set; } [JsonProperty(PropertyName = "resource")] public object Resource { get; set; } //<<<<<<<<<<<< FHIR resource } }
The data my server receives is FHIRCast (http://fhircast.org/) notification messages which contain FHIR Resources (DiagnosticReport, ImagingStudy, Patient, etc.). Example notification:
{ "timestamp": "2019-09-10T14:58:45.988Z", "id": "0d4c9998", "event": { "hub.topic": "joe", "hub.event": "DiagnosticReport-open", "context": [ { "key": "Report", "resource": { "resourceType": "DiagnosticReport", "id": "40012366", "status": "unknown" } } ] } }
Here is the Notify Rest method:
[HttpPost("{topic}")] [Authorize] public async Task<IActionResult> Notify(string topic, [FromBody] Notification notification)
I would appreciate any advice at all. Thanks!
Brian Postlethwaite (Dec 17 2019 at 18:10):
I haven't done this specific interface usage, but imagine that you could leverage inspiration from the project.
Last updated: Apr 12 2022 at 19:14 UTC