Hosting-Neutral Integration

Contents
[ ]

Hosting-neutral integration

DicomWebApplication has no socket, HTTP listener, or dependency-injection requirement. Build it once with standard and/or custom handlers, then give each inbound request a DicomWebRequest whose Path is relative to the DICOMweb service root. The host owns HTTP parsing, authentication, authorization, header and query extraction, request body lifetime, and cancellation. ProcessAsync resolves a route, attaches route values, validates the DICOMweb envelope, dispatches the transaction, and returns a DicomWebApplicationResult.

The following adapter shows the complete public request boundary for a host that already has an HTTP request stream. It does not assume an ASP.NET Core request object:

public static async System.Threading.Tasks.ValueTask<(
    Aspose.Medical.Dicom.Web.DicomWebApplicationResult Result,
    Aspose.Medical.Dicom.Web.DicomWebPayloadReader Payload)> DispatchAsync(
    Aspose.Medical.Dicom.Web.DicomWebApplication application,
    string method,
    string relativePath,
    string? rawQuery,
    System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, System.Collections.Generic.IEnumerable<string>>> headers,
    System.IO.Stream requestBody,
    System.Uri serviceBaseUri,
    bool isWebSocketRequest,
    System.Threading.CancellationToken requestAborted)
{
    Aspose.Medical.Dicom.Web.DicomWebHeaders fields = new(headers.Select(header =>
        System.Collections.Generic.KeyValuePair.Create(
            header.Key, System.Collections.Immutable.ImmutableArray.CreateRange(header.Value))));
    System.Net.Http.Headers.MediaTypeHeaderValue? contentType =
        MediaTypeHeaderValue.TryParse(
            fields.GetFirstOrDefault("Content-Type"), out MediaTypeHeaderValue? parsed)
            ? parsed : null;
    System.IO.Pipelines.PipeReader pipe = PipeReader.Create(
        requestBody, new StreamPipeReaderOptions(leaveOpen: true));
    Aspose.Medical.Dicom.Web.DicomWebPayloadReader payload =
        new(pipe, false, contentType, null);
    try
    {
        Aspose.Medical.Dicom.Web.DicomWebRequest request = new()
        {
            Method = method,
            Path = relativePath,
            Query = Aspose.Medical.Dicom.Web.DicomWebQueryParameters.Parse(rawQuery),
            Headers = fields,
            Body = payload,
            ServiceBaseUri = serviceBaseUri,
            IsWebSocketRequest = isWebSocketRequest
        };
        Aspose.Medical.Dicom.Web.DicomWebApplicationResult result =
            await application.ProcessAsync(request, requestAborted);
        return (result, payload);
    }
    catch
    {
        await payload.DisposeAsync();
        throw;
    }
}

rawQuery may include the leading ?; use / for relativePath when the request targets the service root. Supply the absolute service base URI used to build links in results; pass the host’s abort token. The example passes no custom bulk-data loader. To resolve external bulk-data references in incoming metadata, pass an Aspose.Medical.Dicom.Serialization.IAsyncBulkDataLoader as the payload reader’s fourth constructor argument.

DicomWebPayloadReader is forward-only; leaveOpen: false completes its pipe on disposal while StreamPipeReaderOptions(leaveOpen: true) leaves the host-owned stream open. The caller must dispose the returned Payload after writing the Result, because response content may be lazy. Keep any needed request services alive until writing or notification enumeration ends.

After dispatch, set HTTP status from DicomWebResponse.StatusCode, copy Headers, set Content-Type and optional length from Content, then await Content.WriteToAsync on the host response stream. For DicomWebNotificationSession, apply handshake headers, accept the WebSocket, and send each dataset in Notifications as one DICOM JSON text message. Status/header/WebSocket APIs belong to the selected host. For a concrete HTTP and WebSocket adapter, use ASP.NET Core integration. If ProcessAsync cannot resolve a path, it returns a not-found response; a known path with a different method returns method-not-allowed. Protocol, DICOM validation, JSON, and XML parsing failures are converted to error responses where caught by ProcessAsync. Other exceptions can propagate to the host, which should apply its normal exception policy.