예제 #1
0
        /// <summary>
        /// <see cref="IConsumer{TSingle,TMultiple,TPrimaryKey}.Update(TSingle, string, string, RequestParameter[])">Update</see>
        /// </summary>
        public virtual void Update(
            TSingle obj,
            string zoneId    = null,
            string contextId = null,
            params RequestParameter[] requestParameters)
        {
            if (!RegistrationService.Registered)
            {
                throw new InvalidOperationException("Consumer has not registered.");
            }

            var url = new StringBuilder(EnvironmentUtils.ParseServiceUrl(EnvironmentTemplate))
                      .Append($"/{TypeName}s")
                      .Append($"/{obj.RefId}")
                      .Append(HttpUtils.MatrixParameters(zoneId, contextId))
                      .Append(GenerateQueryParameterString(requestParameters))
                      .ToString();
            string requestBody  = SerialiseSingle(obj);
            string responseBody = HttpUtils.PutRequest(
                url,
                RegistrationService.AuthorisationToken,
                requestBody,
                ConsumerSettings.CompressPayload,
                contentTypeOverride: ContentType.ToDescription(),
                acceptOverride: Accept.ToDescription());

            if (log.IsDebugEnabled)
            {
                log.Debug("Response from PUT request ...");
            }
            if (log.IsDebugEnabled)
            {
                log.Debug(responseBody);
            }
        }
예제 #2
0
        /// <summary>
        /// <see cref="IConsumer{TSingle,TMultiple,TPrimaryKey}.Delete(TPrimaryKey, string, string, RequestParameter[])">Delete</see>
        /// </summary>
        public virtual void Delete(
            TPrimaryKey refId,
            string zoneId    = null,
            string contextId = null,
            params RequestParameter[] requestParameters)
        {
            if (!RegistrationService.Registered)
            {
                throw new InvalidOperationException("Consumer has not registered.");
            }

            string url = new StringBuilder(EnvironmentUtils.ParseServiceUrl(EnvironmentTemplate))
                         .Append($"/{TypeName}s")
                         .Append($"/{refId}")
                         .Append(HttpUtils.MatrixParameters(zoneId, contextId))
                         .Append(GenerateQueryParameterString(requestParameters)).ToString();
            string responseBody = HttpUtils.DeleteRequest(
                url,
                RegistrationService.AuthorisationToken,
                contentTypeOverride: ContentType.ToDescription(),
                acceptOverride: Accept.ToDescription());

            if (log.IsDebugEnabled)
            {
                log.Debug("Response from DELETE request ...");
            }
            if (log.IsDebugEnabled)
            {
                log.Debug(responseBody);
            }
        }
예제 #3
0
        /// <summary>
        /// <see cref="IConsumer{TSingle,TMultiple,TPrimaryKey}.QueryByServicePath(IEnumerable{EqualCondition}, uint?, uint?, string, string, RequestParameter[])">QueryByServicePath</see>
        /// </summary>
        public virtual TMultiple QueryByServicePath(
            IEnumerable <EqualCondition> conditions,
            uint?navigationPage     = null,
            uint?navigationPageSize = null,
            string zoneId           = null,
            string contextId        = null,
            params RequestParameter[] requestParameters)
        {
            if (!RegistrationService.Registered)
            {
                throw new InvalidOperationException("Consumer has not registered.");
            }

            StringBuilder servicePath = new StringBuilder();

            if (conditions != null)
            {
                foreach (EqualCondition condition in conditions)
                {
                    servicePath.Append("/" + condition.Left + "/" + condition.Right);
                }
            }

            string url = new StringBuilder(EnvironmentUtils.ParseServiceUrl(EnvironmentTemplate))
                         .Append(servicePath)
                         .Append($"/{TypeName}s")
                         .Append(HttpUtils.MatrixParameters(zoneId, contextId))
                         .Append(GenerateQueryParameterString(requestParameters)).ToString();

            if (log.IsDebugEnabled)
            {
                log.Debug("Service Path URL is " + url);
            }
            string responseBody;

            if (navigationPage.HasValue && navigationPageSize.HasValue)
            {
                responseBody = HttpUtils.GetRequest(
                    url,
                    RegistrationService.AuthorisationToken,
                    ServiceType.SERVICEPATH,
                    navigationPage: (int)navigationPage,
                    navigationPageSize: (int)navigationPageSize,
                    contentTypeOverride: ContentType.ToDescription(),
                    acceptOverride: Accept.ToDescription());
            }
            else
            {
                responseBody = HttpUtils.GetRequest(
                    url,
                    RegistrationService.AuthorisationToken,
                    ServiceType.SERVICEPATH,
                    contentTypeOverride: ContentType.ToDescription(),
                    acceptOverride: Accept.ToDescription());
            }

            return(DeserialiseMultiple(responseBody));
        }
예제 #4
0
        /// <summary>
        /// <see cref="IConsumer{TSingle,TMultiple,TPrimaryKey}.Query(TPrimaryKey, string, string, RequestParameter[])">Query</see>
        /// </summary>
        public virtual TSingle Query(
            TPrimaryKey refId,
            string zoneId    = null,
            string contextId = null,
            params RequestParameter[] requestParameters)
        {
            if (!RegistrationService.Registered)
            {
                throw new InvalidOperationException("Consumer has not registered.");
            }

            TSingle obj = default(TSingle);

            try
            {
                string url = new StringBuilder(EnvironmentUtils.ParseServiceUrl(EnvironmentTemplate))
                             .Append($"/{TypeName}s")
                             .Append($"/{refId}")
                             .Append(HttpUtils.MatrixParameters(zoneId, contextId))
                             .Append(GenerateQueryParameterString(requestParameters)).ToString();
                string responseBody = HttpUtils.GetRequest(
                    url,
                    RegistrationService.AuthorisationToken,
                    contentTypeOverride: ContentType.ToDescription(),
                    acceptOverride: Accept.ToDescription());
                if (log.IsDebugEnabled)
                {
                    log.Debug("Response from GET request ...");
                }
                if (log.IsDebugEnabled)
                {
                    log.Debug(responseBody);
                }
                obj = DeserialiseSingle(responseBody);
            }
            catch (WebException ex)
            {
                if (WebExceptionStatus.ProtocolError.Equals(ex.Status) && ex.Response != null)
                {
                    HttpStatusCode statusCode = ((HttpWebResponse)ex.Response).StatusCode;

                    if (!HttpStatusCode.NotFound.Equals(statusCode))
                    {
                        throw;
                    }
                }
                else
                {
                    throw;
                }
            }
            catch (Exception)
            {
                throw;
            }

            return(obj);
        }
예제 #5
0
        /// <summary>
        /// <see cref="IConsumer{TSingle,TMultiple,TPrimaryKey}.QueryChangesSince(string, out string, uint?, uint?, string, string, RequestParameter[])">QueryChangesSince</see>
        /// </summary>
        public virtual TMultiple QueryChangesSince(
            string changesSinceMarker,
            out string nextChangesSinceMarker,
            uint?navigationPage     = null,
            uint?navigationPageSize = null,
            string zoneId           = null,
            string contextId        = null,
            params RequestParameter[] requestParameters)
        {
            if (!RegistrationService.Registered)
            {
                throw new InvalidOperationException("Consumer has not registered.");
            }

            RequestParameter[] messageParameters = (requestParameters ?? (new RequestParameter[0]));
            messageParameters = string.IsNullOrWhiteSpace(changesSinceMarker)
                ? messageParameters
                : messageParameters
                                .Concat(new RequestParameter[] { new ChangesSinceQueryParameter(changesSinceMarker) })
                                .ToArray();
            var url = new StringBuilder(EnvironmentUtils.ParseServiceUrl(EnvironmentTemplate))
                      .Append($"/{TypeName}s")
                      .Append(HttpUtils.MatrixParameters(zoneId, contextId))
                      .Append(GenerateQueryParameterString(messageParameters))
                      .ToString();
            WebHeaderCollection responseHeaders;
            string responseBody;

            if (navigationPage.HasValue && navigationPageSize.HasValue)
            {
                responseBody = HttpUtils.GetRequestAndHeaders(
                    url,
                    RegistrationService.AuthorisationToken,
                    ConsumerSettings.CompressPayload,
                    out responseHeaders,
                    navigationPage: (int)navigationPage,
                    navigationPageSize: (int)navigationPageSize,
                    contentTypeOverride: ContentType.ToDescription(),
                    acceptOverride: Accept.ToDescription());
            }
            else
            {
                responseBody = HttpUtils.GetRequestAndHeaders(
                    url,
                    RegistrationService.AuthorisationToken,
                    ConsumerSettings.CompressPayload,
                    out responseHeaders,
                    contentTypeOverride: ContentType.ToDescription(),
                    acceptOverride: Accept.ToDescription());
            }

            nextChangesSinceMarker = responseHeaders[ResponseParameterType.changesSinceMarker.ToDescription()];

            return(DeserialiseMultiple(responseBody));
        }
예제 #6
0
        /// <summary>
        /// <see cref="IConsumer{TSingle,TMultiple,TPrimaryKey}.Delete(IEnumerable{TPrimaryKey}, string, string, RequestParameter[])">Delete</see>
        /// </summary>
        public virtual MultipleDeleteResponse Delete(
            IEnumerable <TPrimaryKey> refIds,
            string zoneId    = null,
            string contextId = null,
            params RequestParameter[] requestParameters)
        {
            if (!RegistrationService.Registered)
            {
                throw new InvalidOperationException("Consumer has not registered.");
            }

            List <deleteIdType> deleteIds = new List <deleteIdType>();

            foreach (TPrimaryKey id in refIds)
            {
                deleteIdType deleteId = new deleteIdType {
                    id = id.ToString()
                };
                deleteIds.Add(deleteId);
            }

            deleteRequestType request = new deleteRequestType {
                deletes = deleteIds.ToArray()
            };
            string url = new StringBuilder(EnvironmentUtils.ParseServiceUrl(EnvironmentTemplate))
                         .Append($"/{TypeName}s")
                         .Append(HttpUtils.MatrixParameters(zoneId, contextId))
                         .Append(GenerateQueryParameterString(requestParameters)).ToString();
            string requestBody  = SerialiserFactory.GetSerialiser <deleteRequestType>(ContentType).Serialise(request);
            string responseBody = HttpUtils.PutRequest(
                url,
                RegistrationService.AuthorisationToken,
                requestBody,
                methodOverride: "DELETE",
                contentTypeOverride: ContentType.ToDescription(),
                acceptOverride: Accept.ToDescription());

            if (log.IsDebugEnabled)
            {
                log.Debug("Response from PUT (DELETE) request ...");
            }
            if (log.IsDebugEnabled)
            {
                log.Debug(responseBody);
            }
            deleteResponseType     updateResponseType = SerialiserFactory.GetSerialiser <deleteResponseType>(Accept).Deserialise(responseBody);
            MultipleDeleteResponse updateResponse     = MapperFactory.CreateInstance <deleteResponseType, MultipleDeleteResponse>(updateResponseType);

            return(updateResponse);
        }
예제 #7
0
        /// <summary>
        /// <see cref="IConsumer{TSingle,TMultiple,TPrimaryKey}.QueryChangesSince(string, out string, uint?, uint?, string, string, RequestParameter[])">QueryChangesSince</see>
        /// </summary>
        public TMultiple DynamicQuery(
            string whereClause,
            uint?navigationPage     = null,
            uint?navigationPageSize = null,
            string zoneId           = null,
            string contextId        = null,
            params RequestParameter[] requestParameters)
        {
            if (!RegistrationService.Registered)
            {
                throw new InvalidOperationException("Consumer has not registered.");
            }

            RequestParameter[] messageParameters = (requestParameters ?? (new RequestParameter[0]));
            messageParameters = string.IsNullOrWhiteSpace(whereClause)
                ? messageParameters
                : messageParameters.Concat(new RequestParameter[] { new DynamicQueryParameter(whereClause) }).ToArray();
            var url = new StringBuilder(EnvironmentUtils.ParseServiceUrl(EnvironmentTemplate))
                      .Append($"/{TypeName}s")
                      .Append(HttpUtils.MatrixParameters(zoneId, contextId))
                      .Append(GenerateQueryParameterString(messageParameters))
                      .ToString();
            string responseBody;

            if (navigationPage.HasValue && navigationPageSize.HasValue)
            {
                responseBody = HttpUtils.GetRequest(
                    url,
                    RegistrationService.AuthorisationToken,
                    ConsumerSettings.CompressPayload,
                    navigationPage: (int)navigationPage,
                    navigationPageSize: (int)navigationPageSize,
                    contentTypeOverride: ContentType.ToDescription(),
                    acceptOverride: Accept.ToDescription());
            }
            else
            {
                responseBody = HttpUtils.GetRequest(
                    url,
                    RegistrationService.AuthorisationToken,
                    ConsumerSettings.CompressPayload,
                    contentTypeOverride: ContentType.ToDescription(),
                    acceptOverride: Accept.ToDescription());
            }

            return(DeserialiseMultiple(responseBody));
        }
예제 #8
0
        /// <summary>
        /// <see cref="IConsumer{TSingle,TMultiple,TPrimaryKey}.Create(TMultiple, bool?, string, string, RequestParameter[])">Create</see>
        /// </summary>
        public virtual MultipleCreateResponse Create(
            TMultiple obj,
            bool?mustUseAdvisory = null,
            string zoneId        = null,
            string contextId     = null,
            params RequestParameter[] requestParameters)
        {
            if (!RegistrationService.Registered)
            {
                throw new InvalidOperationException("Consumer has not registered.");
            }

            var url = new StringBuilder(EnvironmentUtils.ParseServiceUrl(EnvironmentTemplate))
                      .Append($"/{TypeName}s")
                      .Append(HttpUtils.MatrixParameters(zoneId, contextId))
                      .Append(GenerateQueryParameterString(requestParameters))
                      .ToString();
            string requestBody  = SerialiseMultiple(obj);
            string responseBody = HttpUtils.PostRequest(
                url,
                RegistrationService.AuthorisationToken,
                requestBody,
                ConsumerSettings.CompressPayload,
                contentTypeOverride: ContentType.ToDescription(),
                acceptOverride: Accept.ToDescription(),
                mustUseAdvisory: mustUseAdvisory);

            if (log.IsDebugEnabled)
            {
                log.Debug("Response from POST request ...");
            }
            if (log.IsDebugEnabled)
            {
                log.Debug(responseBody);
            }

            createResponseType createResponseType =
                SerialiserFactory.GetSerialiser <createResponseType>(Accept).Deserialise(responseBody);
            MultipleCreateResponse createResponse =
                MapperFactory.CreateInstance <createResponseType, MultipleCreateResponse>(createResponseType);

            return(createResponse);
        }
예제 #9
0
        /// <summary>
        /// <see cref="IConsumer{TSingle,TMultiple,TPrimaryKey}.Query(uint?, uint?, string, string, RequestParameter[])">Query</see>
        /// </summary>
        public virtual TMultiple Query(
            uint?navigationPage     = null,
            uint?navigationPageSize = null,
            string zoneId           = null,
            string contextId        = null,
            params RequestParameter[] requestParameters)
        {
            if (!RegistrationService.Registered)
            {
                throw new InvalidOperationException("Consumer has not registered.");
            }

            var url = new StringBuilder(EnvironmentUtils.ParseServiceUrl(EnvironmentTemplate))
                      .Append($"/{TypeName}s")
                      .Append(HttpUtils.MatrixParameters(zoneId, contextId))
                      .Append(GenerateQueryParameterString(requestParameters))
                      .ToString();
            string responseBody;

            if (navigationPage.HasValue && navigationPageSize.HasValue)
            {
                responseBody = HttpUtils.GetRequest(
                    url,
                    RegistrationService.AuthorisationToken,
                    ConsumerSettings.CompressPayload,
                    navigationPage: (int)navigationPage,
                    navigationPageSize: (int)navigationPageSize,
                    contentTypeOverride: ContentType.ToDescription(),
                    acceptOverride: Accept.ToDescription());
            }
            else
            {
                responseBody = HttpUtils.GetRequest(
                    url,
                    RegistrationService.AuthorisationToken,
                    ConsumerSettings.CompressPayload,
                    contentTypeOverride: ContentType.ToDescription(),
                    acceptOverride: Accept.ToDescription());
            }

            return(DeserialiseMultiple(responseBody));
        }
예제 #10
0
        /// <summary>
        /// Retrieves a Queue that will be used by the Consumer using the subscription id.
        /// </summary>
        /// <param name="subscriptionId">The subscription's identifier.</param>
        /// <returns>Instance of the Subscription if id is valid and subscription is found, null otherwise.</returns>
        private subscriptionType RetrieveSubscription(string subscriptionId)
        {
            string url          = $"{EnvironmentUtils.ParseServiceUrl(Environment, ServiceType.UTILITY, InfrastructureServiceNames.subscriptions)}/{subscriptionId}";
            string responseBody = HttpUtils.GetRequest(
                url,
                RegistrationService.AuthorisationToken,
                contentTypeOverride: ContentType.ToDescription(),
                acceptOverride: Accept.ToDescription());

            if (log.IsDebugEnabled)
            {
                log.Debug($"Response from GET {url} request ...");
            }
            if (log.IsDebugEnabled)
            {
                log.Debug(responseBody);
            }

            return(DeserialiseSubscription(responseBody));
        }
예제 #11
0
        /// <summary>
        /// <see cref="IConsumer{TSingle,TMultiple,TPrimaryKey}.QueryByExample(TSingle, uint?, uint?, string, string, RequestParameter[])">QueryByExample</see>
        /// </summary>
        public virtual TMultiple QueryByExample(
            TSingle obj,
            uint?navigationPage     = null,
            uint?navigationPageSize = null,
            string zoneId           = null,
            string contextId        = null,
            params RequestParameter[] requestParameters)
        {
            if (!RegistrationService.Registered)
            {
                throw new InvalidOperationException("Consumer has not registered.");
            }

            var url = new StringBuilder(EnvironmentUtils.ParseServiceUrl(EnvironmentTemplate))
                      .Append($"/{TypeName}s")
                      .Append(HttpUtils.MatrixParameters(zoneId, contextId))
                      .Append(GenerateQueryParameterString(requestParameters))
                      .ToString();
            string requestBody = SerialiseSingle(obj);
            // TODO: Update PostRequest to accept paging parameters.
            string responseBody = HttpUtils.PostRequest(
                url,
                RegistrationService.AuthorisationToken,
                requestBody,
                ConsumerSettings.CompressPayload,
                methodOverride: "GET",
                contentTypeOverride: ContentType.ToDescription(),
                acceptOverride: Accept.ToDescription());

            if (log.IsDebugEnabled)
            {
                log.Debug("Response from POST (Query by Example) request ...");
            }
            if (log.IsDebugEnabled)
            {
                log.Debug(responseBody);
            }

            return(DeserialiseMultiple(responseBody));
        }
예제 #12
0
        /// <summary>
        /// Create a Queue that will be used by the Consumer.
        /// </summary>
        /// <param name="queue">Queue to create.</param>
        /// <returns>Instance of the created Queue.</returns>
        private queueType CreateQueue(queueType queue)
        {
            string url          = $"{EnvironmentUtils.ParseServiceUrl(Environment, ServiceType.UTILITY, InfrastructureServiceNames.queues)}";
            string requestBody  = SerialiseQueue(queue);
            string responseBody = HttpUtils.PostRequest(
                url,
                RegistrationService.AuthorisationToken,
                requestBody,
                contentTypeOverride: ContentType.ToDescription(),
                acceptOverride: Accept.ToDescription());

            if (log.IsDebugEnabled)
            {
                log.Debug($"Response from POST {url} request ...");
            }
            if (log.IsDebugEnabled)
            {
                log.Debug(responseBody);
            }

            return(DeserialiseQueue(responseBody));
        }
예제 #13
0
        /// <summary>
        /// <see cref="IConsumer{TSingle,TMultiple,TPrimaryKey}.Create(TSingle, bool?, string, string, RequestParameter[])">Create</see>
        /// </summary>
        public virtual TSingle Create(
            TSingle obj,
            bool?mustUseAdvisory = null,
            string zoneId        = null,
            string contextId     = null,
            params RequestParameter[] requestParameters)
        {
            if (!RegistrationService.Registered)
            {
                throw new InvalidOperationException("Consumer has not registered.");
            }

            string url = new StringBuilder(EnvironmentUtils.ParseServiceUrl(EnvironmentTemplate))
                         .Append($"/{TypeName}s")
                         .Append($"/{TypeName}")
                         .Append(HttpUtils.MatrixParameters(zoneId, contextId))
                         .Append(GenerateQueryParameterString(requestParameters)).ToString();
            string requestBody  = SerialiseSingle(obj);
            string responseBody = HttpUtils.PostRequest(
                url,
                RegistrationService.AuthorisationToken,
                requestBody,
                contentTypeOverride: ContentType.ToDescription(),
                acceptOverride: Accept.ToDescription(),
                mustUseAdvisory: mustUseAdvisory);

            if (log.IsDebugEnabled)
            {
                log.Debug("Response from POST request ...");
            }
            if (log.IsDebugEnabled)
            {
                log.Debug(responseBody);
            }

            return(DeserialiseSingle(responseBody));
        }
예제 #14
0
        public virtual IHttpActionResult BroadcastEvents(string zoneId = null, string contextId = null)
        {
            var  eventService    = Service as IEventService <TMultiple>;
            bool eventsSupported = (eventService != null);

            if (!eventsSupported)
            {
                return(BadRequest("Support for SIF Events has not been implemented."));
            }

            IHttpActionResult result;

            try
            {
                IRegistrationService registrationService = RegistrationManager.GetProviderRegistrationService(
                    ProviderSettings,
                    sessionService);

                if (registrationService is NoRegistrationService)
                {
                    result = BadRequest("SIF Events are only supported in a BROKERED environment.");
                }
                else
                {
                    IEventIterator <TMultiple> eventIterator = eventService.GetEventIterator(zoneId, contextId);

                    if (eventIterator == null)
                    {
                        result = BadRequest("SIF Events implementation is not valid.");
                    }
                    else
                    {
                        Model.Infrastructure.Environment environment = registrationService.Register();

                        // Retrieve the current Authorisation Token.
                        AuthorisationToken token = registrationService.AuthorisationToken;

                        // Retrieve the EventsConnector endpoint URL.
                        string url = EnvironmentUtils.ParseServiceUrl(
                            environment,
                            ServiceType.UTILITY,
                            InfrastructureServiceNames.eventsConnector);

                        while (eventIterator.HasNext())
                        {
                            SifEvent <TMultiple> sifEvent = eventIterator.GetNext();

                            var requestHeaders = new NameValueCollection()
                            {
                                { EventParameterType.eventAction.ToDescription(), sifEvent.EventAction.ToDescription() },
                                { EventParameterType.messageId.ToDescription(), sifEvent.Id.ToString() },
                                { EventParameterType.messageType.ToDescription(), "EVENT" },
                                { EventParameterType.serviceName.ToDescription(), $"{TypeName}s" }
                            };

                            switch (sifEvent.EventAction)
                            {
                            case EventAction.UPDATE_FULL:
                                requestHeaders.Add(EventParameterType.Replacement.ToDescription(), "FULL");
                                break;

                            case EventAction.UPDATE_PARTIAL:
                                requestHeaders.Add(EventParameterType.Replacement.ToDescription(), "PARTIAL");
                                break;
                            }

                            string requestBody = SerialiseEvents(sifEvent.SifObjects);
                            HttpUtils.PostRequest(
                                url,
                                token,
                                requestBody,
                                ProviderSettings.CompressPayload,
                                contentTypeOverride: ContentType.ToDescription(),
                                acceptOverride: Accept.ToDescription(),
                                requestHeaders: requestHeaders);
                        }

                        result = Ok();
                    }
                }
            }
            catch (Exception e)
            {
                result = InternalServerError(e);
            }

            return(result);
        }
예제 #15
0
        /// <summary>
        /// Periodically process SIF Events.
        /// </summary>
        /// <param name="cancellationToken">Notification that processing should be cancelled.</param>
        private void ProcessEvents(CancellationToken cancellationToken)
        {
            while (true)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                bool     getEvents       = true;
                TimeSpan waitTime        = TimeSpan.FromSeconds(SettingsManager.ConsumerSettings.EventProcessingWaitTime);
                string   url             = $"{EnvironmentUtils.ParseServiceUrl(Environment, ServiceType.UTILITY, InfrastructureServiceNames.queues)}/{Queue.id}/messages";
                string   deleteMessageId = null;

                // Read from the message queue until no more messages are found.
                do
                {
                    try
                    {
                        string deleteMessageIdMatrixParameter = (deleteMessageId == null ? "" : $";deleteMessageId={deleteMessageId.Trim()}");
                        if (log.IsDebugEnabled)
                        {
                            log.Debug($"Making a request for an event message from {url}{deleteMessageIdMatrixParameter}.");
                        }
                        string responseBody = HttpUtils.GetRequestAndHeaders(
                            $"{url}{deleteMessageIdMatrixParameter}",
                            RegistrationService.AuthorisationToken,
                            out WebHeaderCollection responseHeaders,
                            contentTypeOverride: ContentType.ToDescription(),
                            acceptOverride: Accept.ToDescription(),
                            deleteMessageId: deleteMessageId);
                        string contextId = responseHeaders?[EventParameterType.contextId.ToDescription()];
                        deleteMessageId = responseHeaders?[EventParameterType.messageId.ToDescription()];
                        string minWaitTimeValue = responseHeaders?[EventParameterType.minWaitTime.ToDescription()];
                        string zoneId           = responseHeaders?[EventParameterType.zoneId.ToDescription()];

                        if (!string.IsNullOrWhiteSpace(minWaitTimeValue))
                        {
                            if (double.TryParse(minWaitTimeValue, out double minWaitTime) && (TimeSpan.FromSeconds(minWaitTime) > waitTime))
                            {
                                waitTime = TimeSpan.FromSeconds(minWaitTime);
                            }
                        }

                        // Call the appropriate event handler for messages read.
                        if (!string.IsNullOrWhiteSpace(responseBody))
                        {
                            try
                            {
                                TMultiple obj         = DeserialiseMultiple(responseBody);
                                string    eventAction = responseHeaders?[EventParameterType.eventAction.ToDescription()];

                                if (EventAction.CREATE.ToDescription().Equals(eventAction))
                                {
                                    if (log.IsDebugEnabled)
                                    {
                                        log.Debug($"Received create event message.");
                                    }
                                    OnCreateEvent(obj, zoneId, contextId);
                                }
                                else if (EventAction.DELETE.ToDescription().Equals(eventAction))
                                {
                                    if (log.IsDebugEnabled)
                                    {
                                        log.Debug($"Received delete event message.");
                                    }
                                    OnDeleteEvent(obj, zoneId, contextId);
                                }
                                else if ("UPDATE".Equals(eventAction))
                                {
                                    string replacement = responseHeaders?[EventParameterType.Replacement.ToDescription()];

                                    if ("FULL".Equals(replacement))
                                    {
                                        if (log.IsDebugEnabled)
                                        {
                                            log.Debug($"Received update (full) event message.");
                                        }
                                        OnUpdateEvent(obj, false, zoneId, contextId);
                                    }
                                    else if ("PARTIAL".Equals(replacement))
                                    {
                                        if (log.IsDebugEnabled)
                                        {
                                            log.Debug($"Received update (partial) event message.");
                                        }
                                        OnUpdateEvent(obj, true, zoneId, contextId);
                                    }
                                    else
                                    {
                                        if (log.IsDebugEnabled)
                                        {
                                            log.Debug($"Received update (partial) event message.");
                                        }
                                        OnUpdateEvent(obj, true, zoneId, contextId);
                                    }
                                }
                                else
                                {
                                    BaseException eventException = new EventException($"Event action {eventAction} not recognised for message received from {url}.");
                                    if (log.IsWarnEnabled)
                                    {
                                        log.Warn(eventException.Message);
                                    }
                                    ResponseError error = new ResponseError {
                                        Id = eventException.ExceptionReference, Code = 500, Message = eventException.Message, Description = responseBody, Scope = TypeName
                                    };
                                    OnErrorEvent(error);
                                }
                            }
                            catch (SerializationException e)
                            {
                                BaseException eventException = new EventException($"Event message received from {url} could not be processed due to the following error:\n{e.GetBaseException().Message}.", e);
                                if (log.IsWarnEnabled)
                                {
                                    log.Warn(e.Message);
                                }
                                ResponseError error = new ResponseError {
                                    Id = eventException.ExceptionReference, Code = 500, Message = e.Message, Description = responseBody, Scope = TypeName
                                };
                                OnErrorEvent(error);
                            }
                        }
                        else
                        {
                            if (log.IsDebugEnabled)
                            {
                                log.Debug($"No event messages.");
                            }
                            getEvents = false;
                        }
                    }
                    catch (Exception e)
                    {
                        string errorMessage = $"Error processing event messages due to the following error:\n{e.GetBaseException().Message}.";
                        if (log.IsErrorEnabled)
                        {
                            log.Error($"{errorMessage}\n{e.StackTrace}");
                        }
                        getEvents = false;
                    }
                } while (getEvents);

                if (log.IsDebugEnabled)
                {
                    log.Debug($"Wait time is {waitTime.Seconds} seconds.");
                }

                // Wait an appropriate amount of time before reading from the message queue again.
                Thread.Sleep(waitTime);
            }
        }