private HttpWebRequest createRequest(Uri location, bool forBundle) { Uri endpoint = location; if (UseFormatParam) { var rl = new ResourceLocation(location); rl.SetParam(Util.RESTPARAM_FORMAT, ContentType.BuildFormatParam(PreferredFormat)); endpoint = rl.ToUri(); } var req = (HttpWebRequest)HttpWebRequest.Create(endpoint); var agent = "FhirClient for FHIR " + Model.ModelInfo.Version; req.Method = "GET"; #if NETFX_CORE req.Headers[HttpRequestHeader.UserAgent] = agent; #else req.UserAgent = agent; #endif if (!UseFormatParam) { req.Accept = ContentType.BuildContentType(PreferredFormat, forBundle); } return(req); }
/// <summary> /// Send a Bundle to a path on the server /// </summary> /// <param name="bundle">The contents of the Bundle to be sent</param> /// <param name="path">A path on the server to send the Bundle to</param> /// <returns>True if the bundle was successfully delivered, false otherwise</returns> /// <remarks>This method differs from Batch, in that it can be used to deliver a Bundle /// at the endpoint for messages, documents or binaries, instead of the batched update /// REST endpoint.</remarks> public bool DeliverBundle(Bundle bundle, string path) { if (Endpoint == null) { throw new InvalidOperationException("Endpoint must be provided using either the Endpoint property or the FhirClient constructor"); } byte[] data; string contentType = ContentType.BuildContentType(PreferredFormat, false); if (PreferredFormat == ContentType.ResourceFormat.Json) { data = FhirSerializer.SerializeBundleToJsonBytes(bundle); } else if (PreferredFormat == ContentType.ResourceFormat.Xml) { data = FhirSerializer.SerializeBundleToXmlBytes(bundle); } else { throw new ArgumentException("Cannot encode a batch into format " + PreferredFormat.ToString()); } var req = createRequest(Endpoint, true); req.Method = "POST"; req.ContentType = contentType; prepareRequest(req, data); return(doRequest(req, HttpStatusCode.OK, () => true)); }
/// <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>())); }
/// <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; } } }
/// <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>())); }