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
        /// <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 #8
0
        /// <summary>
        /// Serialize the reply
        /// </summary>
        public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
        {
            try
            {
                // Outbound control
                var     format  = WebContentFormat.Raw;
                Message request = OperationContext.Current.RequestContext.RequestMessage;
                HttpRequestMessageProperty httpRequest = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
                string accepts     = httpRequest.Headers[HttpRequestHeader.Accept],
                       contentType = httpRequest.Headers[HttpRequestHeader.ContentType],
                       formatParm  = httpRequest.QueryString;

                Message reply = null;

                // Result is serializable
                if (result?.GetType().GetCustomAttribute <XmlTypeAttribute>() != null ||
                    result?.GetType().GetCustomAttribute <JsonObjectAttribute>() != null)
                {
                    XmlSerializer xsz = s_serializers[result.GetType()];
                    MemoryStream  ms  = new MemoryStream();
                    xsz.Serialize(ms, result);
                    format      = WebContentFormat.Xml;
                    contentType = "application/xml+fhir";
                    ms.Seek(0, SeekOrigin.Begin);

                    // The request was in JSON or the accept is JSON
                    if (accepts?.StartsWith("application/json+fhir") == true ||
                        contentType?.StartsWith("application/json+fhir") == true ||
                        formatParm.Contains("_format=json"))
                    {
                        // Parse XML object
                        Object fhirObject = null;
                        using (StreamReader sr = new StreamReader(ms))
                        {
                            String fhirContent = sr.ReadToEnd();
                            var    parser      = new FhirXmlParser();
                            parser.Settings.AllowUnrecognizedEnums = true;
                            fhirObject = parser.Parse <Resource>(fhirContent);
                        }

                        // Now we serialize to JSON
                        byte[] body = FhirSerializer.SerializeResourceToJsonBytes(fhirObject as Hl7.Fhir.Model.Resource);

                        // Prepare reply for the WCF pipeline
                        format      = WebContentFormat.Raw;
                        contentType = "application/json+fhir";
                        reply       = Message.CreateMessage(messageVersion, this.m_operationDescription?.Messages[1]?.Action, new RawBodyWriter(body));
                    }
                    // The request was in XML and/or the accept is JSON
                    else
                    {
                        reply = Message.CreateMessage(messageVersion, this.m_operationDescription?.Messages[1]?.Action, XmlDictionaryReader.Create(ms));
                    }
                }
                else if (result is XmlSchema)
                {
                    MemoryStream ms = new MemoryStream();
                    (result as XmlSchema).Write(ms);
                    ms.Seek(0, SeekOrigin.Begin);
                    format      = WebContentFormat.Xml;
                    contentType = "text/xml";
                    reply       = Message.CreateMessage(messageVersion, this.m_operationDescription.Messages[1].Action, XmlDictionaryReader.Create(ms));
                }
                else if (result is Stream) // TODO: This is messy, clean it up
                {
                    reply = Message.CreateMessage(messageVersion, this.m_operationDescription.Messages[1].Action, new RawBodyWriter(result as Stream));
                }

                reply.Properties.Add(WebBodyFormatMessageProperty.Name, new WebBodyFormatMessageProperty(format));
                WebOperationContext.Current.OutgoingResponse.ContentType = contentType;
                WebOperationContext.Current.OutgoingResponse.Headers.Add("X-PoweredBy", String.Format("{0} v{1} ({2})", Assembly.GetEntryAssembly().GetName().Name, Assembly.GetEntryAssembly().GetName().Version, Assembly.GetEntryAssembly().GetCustomAttribute <AssemblyInformationalVersionAttribute>()?.InformationalVersion));
                WebOperationContext.Current.OutgoingResponse.Headers.Add("X-GeneratedOn", DateTime.Now.ToString("o"));

                return(reply);
            }
            catch (Exception e)
            {
                this.m_traceSource.TraceEvent(TraceEventType.Error, e.HResult, e.ToString());
                throw;
            }
        }