1

I'm currently trying to wrap my head around routing with FHIR search.

In the paragraph 2.1.1.48 String in the webpage https://www.hl7.org/fhir/search.html, there's a section about how you can use modifiers to return results that includes or matches the supplied parameter value.

Ex:

[base]/Patient?name=eve
[base]/Patient?name:contains=eve    
[base]/Patient?name:exact=Eve

I've never seen such URLs with these custom modifiers "?name:exact/contains" being accepted in f.ex. a web api service out of the box.

As far as I can see, it is not allowed to write something in the lines of

[Route("{type}/name:contains/{name}")] 
public HttpResponseMessage GetContainsName(string name){

//do something 
}

[Route("{type}/name:exact/{name}")]
public HttpResponseMessage GetExactName(string name) {
//do something else
}
  • Please have a look at this question: http://stackoverflow.com/questions/2053132/is-a-colon-safe-for-friendly-url-use – A_A Apr 08 '16 at 14:17

2 Answers2

1

This is a possible solution to get a FHIR server up and running. I have used some code from the Sparks.Engine so it is easier to get the modifiers working as well as "decoding" the url.

You'll hopefully get hits in either of the methods

The methods should accept urls like these

fhir/Patient/1
fhir/Patient?name=something
fhir/?_query="nameOfQuery"&name:contains="someName"

The code for the server itself looks like this

namespace FHIRServer.Controllers
{
    [RoutePrefix("fhir"), EnableCors("*", "*", "*", "*")]
    [RouteDataValuesOnly]
    public class FhirController : ApiController
    {
        public FhirController()
        {
        }

        [HttpGet, Route("{type}")]
        public HttpResponseMessage ResourceQuery(string type)
        {
            var searchParams = Request.GetSearchParams();

            // do something with the search params
        }

        [HttpGet, Route("")]
        public HttpResponseMessage Query(string _query)
        {
            var searchParams = Request.GetSearchParams();

            // do something with the search params
        }
    }
}

The Request.GetSearchParams() is a part of Sparks.Engine, which you can find here https://github.com/furore-fhir/spark I've added Sparks.Engine to our FHIR solution since it has a lot of features already implemented.

The

 var searchParams = Request.GetSearchParams();

helps out parsing the different parameters in the url and makes it a lot easier to go forward from there.

This answer is inspired by the previous answer in this thread by Brian.

0

In the sqlonfhir server (and I believe the Spark server also) the processing of the parameters is not done through webapi routing.

We both use the routing to extract the resourcename, id, operation (and history and versionId) all other functionality is done manually by extracting the content from the RequestUrl and processing it.

[HttpGet, Route("{ResourceName}/{id}/_history/{vid}")]
public HttpResponseMessage Get(string ResourceName, string id, string vid)
{
    var buri = this.CalculateBaseURI("{ResourceName}");
    fhirstore.RegisterKnownUrl(buri);

    if (!Id.IsValidValue(id))
    {
        throw new FhirServerException(HttpStatusCode.BadRequest, "ID [" + id + "] is not a valid FHIR Resource ID");
    }

    IModelBase model = GetModel(ResourceName, GetInputs(buri));
    var resource = model.Get(id, vid, summary);
    if (resource != null)
    {
        var msg = Request.ResourceResponse(resource, HttpStatusCode.OK);
        msg.Headers.Location = resource.ResourceIdentity().WithBase(resource.ResourceBase);
        msg.Headers.Add("ETag", String.Format("\"{0}\"", resource.Meta.VersionId));
        return msg;
    }

    // this request is a "you wanted what?"
    return Request.CreateResponse(HttpStatusCode.NotFound);
}

(Not a complete code extract - I've stripped the code that handles binary resources, and the _summary parameter content processing)

Another Item from this code that is worth noting, that processing is done within the model (so I can unit test external to the web context). And the CalculateBaseURI method ensures that the URL on the request is applied to the location on the result, without needing to have a configuration setting that tells the server what to put there.

And while i'm discussing it, we use media formatters to parse the resources content too.

  • I had to investigate a lot in the Sparks.Engine code to see how url's are really processed. What you are saying is true, the url is processed in the code. – Harald S. Hanssen Apr 22 '16 at 07:45