Example #1
0
        private HttpWebRequest prepareRequest(string method, Uri uri, object data, IEnumerable <Tag> tags, bool expectBundleResponse)
        {
            byte[] body = null;

            Uri api = uri;

            if (UseFormatParam)
            {
                api = api.AddParam(HttpUtil.RESTPARAM_FORMAT, ContentType.BuildFormatParam(PreferredFormat));
            }

            var req = initializeRequest(api, method);

            if (!UseFormatParam)
            {
                req.Accept = ContentType.BuildContentType(PreferredFormat, forBundle: expectBundleResponse);
            }

            if (data is Binary)
            {
                var bin = (Binary)data;
                body            = bin.Content;
                req.ContentType = bin.ContentType;
            }
            else if (data is Resource)
            {
                body = PreferredFormat == ResourceFormat.Xml ?
                       FhirSerializer.SerializeResourceToXmlBytes((Resource)data) :
                       FhirSerializer.SerializeResourceToJsonBytes((Resource)data);

                req.ContentType = ContentType.BuildContentType(PreferredFormat, false);
            }
            else if (data is Bundle)
            {
                body = PreferredFormat == ResourceFormat.Xml ?
                       FhirSerializer.SerializeBundleToXmlBytes((Bundle)data) :
                       FhirSerializer.SerializeBundleToJsonBytes((Bundle)data);

                req.ContentType = ContentType.BuildContentType(PreferredFormat, true);
            }
            else if (data is TagList)
            {
                body = PreferredFormat == ResourceFormat.Xml ?
                       FhirSerializer.SerializeTagListToXmlBytes((TagList)data) :
                       FhirSerializer.SerializeTagListToJsonBytes((TagList)data);

                req.ContentType = ContentType.BuildContentType(PreferredFormat, false);
            }

            if (tags != null)
            {
                req.Headers[HttpUtil.CATEGORY] = HttpUtil.BuildCategoryHeader(tags);
            }

            if (body != null)
            {
                writeBody(req, body);
            }
            return(req);
        }
Example #2
0
        /// <summary>
        /// Update (or create) a resource at a given endpoint
        /// </summary>
        /// <param name="entry">A ResourceEntry containing the resource to update</param>
        /// <param name="versionAware">Whether or not version aware update is used.</param>
        /// <typeparam name="TResource">The type of resource that is being updated</typeparam>
        /// <returns>The resource as updated on the server. Throws an exception when the update failed,
        /// in particular may throw an exception when the server returns a 409 when a conflict is detected
        /// while using version-aware updates or 412 if the server requires version-aware updates.</returns>
        public ResourceEntry <TResource> Update <TResource>(ResourceEntry <TResource> entry, bool versionAware = false)
            where TResource : Resource, new()
        {
            if (entry == null)
            {
                throw new ArgumentNullException("entry");
            }
            if (entry.Resource == null)
            {
                throw new ArgumentException("Entry does not contain a Resource to update", "entry");
            }
            if (entry.Id == null)
            {
                throw new ArgumentException("Entry needs a non-null entry.id to send the update to", "entry");
            }
            if (versionAware && entry.SelfLink == null)
            {
                throw new ArgumentException("When requesting version-aware updates, Entry.SelfLink may not be null.", "entry");
            }

            string contentType = null;

            byte[] data = null;

            if (entry.Resource is Binary)
            {
                var bin = entry.Resource as Binary;
                data        = bin.Content;
                contentType = bin.ContentType;
            }
            else
            {
                data = PreferredFormat == ContentType.ResourceFormat.Xml ?
                       FhirSerializer.SerializeResourceToXmlBytes(entry.Resource) :
                       FhirSerializer.SerializeResourceToJsonBytes(entry.Resource);
                contentType = ContentType.BuildContentType(PreferredFormat, false);
            }

            var req = createRequest(entry.Id, false);

            req.Method      = "PUT";
            req.ContentType = contentType;
            prepareRequest(req, data, entry.Tags);

            // If a version id is given, post the data to a version-specific url
            if (versionAware)
            {
                req.Headers[HttpRequestHeader.ContentLocation] = entry.SelfLink.ToString();
            }

            return(doRequest(req, new HttpStatusCode[] { HttpStatusCode.Created, HttpStatusCode.OK },
                             () => resourceEntryFromResponse <TResource>()));
        }
Example #3
0
        /// <summary>
        /// Validates whether the contents of the resource would be acceptable as an update
        /// </summary>
        /// <param name="entry">The entry containing the updated Resource to validate</param>
        /// <returns>null if validation succeeded, otherwise returns OperationOutcome detailing the validation errors.
        /// If the server returned an error, but did not return an OperationOutcome resource, an exception will be
        /// thrown.</returns>
        public OperationOutcome Validate <TResource>(ResourceEntry <TResource> entry) where TResource : Resource, new()
        {
            if (entry == null)
            {
                throw new ArgumentNullException("entry");
            }
            if (entry.Resource == null)
            {
                throw new ArgumentException("Entry does not contain a Resource to validate", "entry");
            }
            if (entry.Id == null)
            {
                throw new ArgumentException("Entry needs a non-null entry.id to use for validation", "entry");
            }

            string contentType = ContentType.BuildContentType(PreferredFormat, false);

            byte[] data = PreferredFormat == ContentType.ResourceFormat.Xml ?
                          FhirSerializer.SerializeResourceToXmlBytes(entry.Resource) :
                          FhirSerializer.SerializeResourceToJsonBytes(entry.Resource);

            var rl = new ResourceLocation(entry.Id);

            rl.Operation = ResourceLocation.RESTOPER_VALIDATE;
            var req = createRequest(rl.ToUri(), false);

            req.Method      = "POST";
            req.ContentType = contentType;
            prepareRequest(req, data, entry.Tags);

            try
            {
                doRequest(req, HttpStatusCode.OK, () => true);
                return(null);
            }
            catch (FhirOperationException foe)
            {
                if (foe.Outcome != null)
                {
                    return(foe.Outcome);
                }
                else
                {
                    throw foe;
                }
            }
        }
Example #4
0
        public void AvoidBOMUse()
        {
            Bundle b = new Bundle();

            var data = FhirSerializer.SerializeBundleToJsonBytes(b);

            Assert.IsFalse(data[0] == Encoding.UTF8.GetPreamble()[0]);

            data = FhirSerializer.SerializeBundleToXmlBytes(b);
            Assert.IsFalse(data[0] == Encoding.UTF8.GetPreamble()[0]);

            Patient p = new Patient();

            data = FhirSerializer.SerializeResourceToJsonBytes(p);
            Assert.IsFalse(data[0] == Encoding.UTF8.GetPreamble()[0]);

            data = FhirSerializer.SerializeResourceToXmlBytes(p);
            Assert.IsFalse(data[0] == Encoding.UTF8.GetPreamble()[0]);
        }
        public static HttpResponseMessage ToHttpResponseMessage(this OperationOutcome outcome, ResourceFormat target, HttpRequestMessage request)
        {
            byte[] data = null;
            if (target == ResourceFormat.Xml)
            {
                data = FhirSerializer.SerializeResourceToXmlBytes((OperationOutcome)outcome);
            }
            else if (target == ResourceFormat.Json)
            {
                data = FhirSerializer.SerializeResourceToJsonBytes((OperationOutcome)outcome);
            }

            HttpResponseMessage response = new HttpResponseMessage();

            //setResponseHeaders(response, target);
            response.Content = new ByteArrayContent(data);
            setContentHeaders(response, target);

            return(response);
        }
Example #6
0
        public void SetBody(Resource resource, ResourceFormat format)
        {
            if (resource == null)
            {
                throw Error.ArgumentNull("resource");
            }

            if (resource is Binary)
            {
                var bin = (Binary)resource;
                _body        = bin.Content;
                _contentType = bin.ContentType;
            }
            else
            {
                _body = format == ResourceFormat.Xml ?
                        FhirSerializer.SerializeResourceToXmlBytes(resource, summary: false) :
                        FhirSerializer.SerializeResourceToJsonBytes(resource, summary: false);

                _contentType = ContentType.BuildContentType(format, forBundle: false);
            }
        }
Example #7
0
        public void SerializationDoesNotEmitXmlHeader()
        {
            Bundle b      = createTestBundle();
            var    actual = FhirSerializer.SerializeBundleToXml(b);

            Assert.IsFalse(actual.StartsWith("<?xml"));

            var data = FhirSerializer.SerializeBundleToXmlBytes(b);

            actual = System.Text.Encoding.UTF8.GetString(data);
            Assert.IsFalse(actual.StartsWith("<?xml"));


            Patient p = new Patient();

            actual = FhirSerializer.SerializeResourceToXml(p);
            Assert.IsFalse(actual.StartsWith("<?xml"));

            data   = FhirSerializer.SerializeResourceToXmlBytes(p);
            actual = System.Text.Encoding.UTF8.GetString(data);
            Assert.IsFalse(actual.StartsWith("<?xml"));
        }
Example #8
0
        /// <summary>
        /// Create a resource
        /// </summary>
        /// <param name="collectionEndpoint">Endpoint where the resource is sent to be created</param>
        /// <param name="resource">The resource instance to create</param>
        /// <param name="tags">Optional. List of Tags to add to the created instance.</param>
        /// <returns>The resource as created on the server, or an exception if the create failed.</returns>
        /// <typeparam name="TResource">The type of resource to create</typeparam>
        /// <remarks><para>The returned resource need not be the same as the resources passed as a parameter,
        /// since the server may have updated or changed part of the data because of business rules.</para>
        /// </remarks>
        public ResourceEntry <TResource> Create <TResource>(Uri collectionEndpoint, TResource resource, IEnumerable <Tag> tags = null) where TResource : Resource, new()
        {
            if (collectionEndpoint == null)
            {
                throw new ArgumentNullException("collectionEndpoint");
            }
            if (resource == null)
            {
                throw new ArgumentNullException("resource");
            }

            string contentType = null;

            byte[] data = null;

            if (resource is Binary)
            {
                var bin = resource as Binary;
                data        = bin.Content;
                contentType = bin.ContentType;
            }
            else
            {
                data = PreferredFormat == ContentType.ResourceFormat.Xml ?
                       FhirSerializer.SerializeResourceToXmlBytes(resource) :
                       FhirSerializer.SerializeResourceToJsonBytes(resource);
                contentType = ContentType.BuildContentType(PreferredFormat, false);
            }

            var req = createRequest(collectionEndpoint, false);

            req.Method      = "POST";
            req.ContentType = contentType;
            prepareRequest(req, data, tags);

            return(doRequest(req, HttpStatusCode.Created, () => resourceEntryFromResponse <TResource>()));
        }
Example #9
0
        /// <summary>
        /// Deserialize the request
        /// </summary>
        public void DeserializeRequest(Message request, object[] parameters)
        {
            try
            {
                HttpRequestMessageProperty httpRequest = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
                string contentType = httpRequest.Headers[HttpRequestHeader.ContentType];


                UriTemplateMatch templateMatch = (UriTemplateMatch)request.Properties.SingleOrDefault(o => o.Value is UriTemplateMatch).Value;
                // Not found
                if (templateMatch == null)
                {
                    throw new WebFaultException(HttpStatusCode.NotFound);
                }

                for (int pNumber = 0; pNumber < parameters.Length; pNumber++)
                {
                    var parm = this.m_operationDescription.Messages[0].Body.Parts[pNumber];

                    // Simple parameter
                    if (templateMatch.BoundVariables.AllKeys.Any(o => o.ToString().ToLower() == parm.Name.ToLower()))
                    {
                        var rawData = templateMatch.BoundVariables[parm.Name];
                        parameters[pNumber] = Convert.ChangeType(rawData, parm.Type);
                    }
                    // Use XML Serializer
                    else if (contentType?.StartsWith("application/xml+fhir") == true)
                    {
                        var messageFormatProperty     = (WebBodyFormatMessageProperty)request.Properties[WebBodyFormatMessageProperty.Name];
                        XmlDictionaryReader rawReader = request.GetReaderAtBodyContents();

                        switch (messageFormatProperty.Format)
                        {
                        case WebContentFormat.Raw:
                        {
                            rawReader.ReadStartElement("Binary");
                            byte[] rawBody = rawReader.ReadContentAsBase64();

                            using (MemoryStream ms = new MemoryStream(rawBody))
                            {
                                using (XmlReader bodyReader = XmlReader.Create(ms))
                                {
                                    while (bodyReader.NodeType != XmlNodeType.Element)
                                    {
                                        bodyReader.Read();
                                    }

                                    Type eType = s_knownTypes.FirstOrDefault(o => o.GetCustomAttribute <XmlRootAttribute>()?.ElementName == bodyReader.LocalName &&
                                                                             o.GetCustomAttribute <XmlRootAttribute>()?.Namespace == bodyReader.NamespaceURI);
                                    XmlSerializer xsz = s_serializers[eType];
                                    parameters[pNumber] = xsz.Deserialize(bodyReader);
                                }
                            }
                        }

                        break;

                        case WebContentFormat.Xml:
                        {
                            using (rawReader)
                            {
                                rawReader.MoveToStartElement();
                                Type eType = s_knownTypes.FirstOrDefault(o => o.GetCustomAttribute <XmlRootAttribute>()?.ElementName == rawReader.LocalName && o.GetCustomAttribute <XmlRootAttribute>()?.Namespace == rawReader.NamespaceURI);

                                this.m_traceSource.TraceEvent(TraceEventType.Information, 0, "Contract: {0}", typeof(IFhirServiceContract).Name);
                                this.m_traceSource.TraceEvent(TraceEventType.Information, 0, "Attempting to deserialize type: {0}", eType?.Name);

                                XmlSerializer xsz = s_serializers[eType];
                                parameters[pNumber] = xsz.Deserialize(rawReader);
                            }
                        }
                        break;
                        }
                    }
                    // Use JSON Serializer
                    else if (contentType?.StartsWith("application/json+fhir") == true)
                    {
                        // Read the binary contents form the WCF pipeline
                        XmlDictionaryReader bodyReader = request.GetReaderAtBodyContents();
                        bodyReader.ReadStartElement("Binary");
                        byte[] rawBody = bodyReader.ReadContentAsBase64();

                        // Now read the JSON data
                        Object fhirObject = null;
                        using (MemoryStream mstream = new MemoryStream(rawBody))
                            using (StreamReader sr = new StreamReader(mstream))
                            {
                                string fhirContent = sr.ReadToEnd();
                                fhirObject = FhirParser.ParseFromJson(fhirContent);
                            }

                        // Now we want to serialize the FHIR MODEL object and re-parse as our own API bundle object
                        MemoryStream ms = new MemoryStream(FhirSerializer.SerializeResourceToXmlBytes(fhirObject as Hl7.Fhir.Model.Resource));

                        XmlSerializer xsz = s_serializers[fhirObject?.GetType()];
                        parameters[0] = xsz.Deserialize(ms);
                    }
                    else if (contentType != null)// TODO: Binaries
                    {
                        throw new InvalidOperationException("Invalid request format");
                    }
                }
            }
            catch (Exception e)
            {
                this.m_traceSource.TraceEvent(TraceEventType.Error, e.HResult, e.ToString());
                throw;
            }
        }