示例#1
0
        /// <summary>
        /// Create an instance based on the specified service.
        /// </summary>
        /// <param name="service">Service used for managing the object type.</param>
        /// <param name="settings">Provider settings. If null, Provider settings will be read from the SifFramework.config file.</param>
        /// <param name="sessionService">Provider session service. If null, the Provider session will be stored in the SifFramework.config file.</param>
        /// <exception cref="ArgumentNullException">service is null.</exception>
        protected Provider(
            IProviderService <TSingle, TMultiple> service,
            IFrameworkSettings settings    = null,
            ISessionService sessionService = null)
        {
            Service             = service ?? throw new ArgumentNullException(nameof(service));
            ProviderSettings    = settings ?? SettingsManager.ProviderSettings;
            this.sessionService = sessionService ?? SessionsManager.ProviderSessionService;

            if (EnvironmentType.DIRECT.Equals(ProviderSettings.EnvironmentType))
            {
                AuthenticationService =
                    new DirectAuthenticationService(new ApplicationRegisterService(), new EnvironmentService());
            }
            else if (EnvironmentType.BROKERED.Equals(ProviderSettings.EnvironmentType))
            {
                AuthenticationService = new BrokeredAuthenticationService(
                    new ApplicationRegisterService(),
                    new EnvironmentService(),
                    ProviderSettings,
                    this.sessionService);
            }

            AuthorisationService = new AuthorisationService(AuthenticationService);
        }
        /// <summary>
        /// <see cref="IProvider{TTSingle,TMultiple,TPrimaryKey}.Put(TMultiple, string[], string[])">Put</see>
        /// </summary>
        public override IHttpActionResult Put(
            TMultiple obj,
            [MatrixParameter] string[] zoneId    = null,
            [MatrixParameter] string[] contextId = null)
        {
            if (!AuthenticationService.VerifyAuthenticationHeader(Request.Headers, out string sessionToken))
            {
                return(Unauthorized());
            }

            // Check ACLs and return StatusCode(HttpStatusCode.Forbidden) if appropriate.
            if (!AuthorisationService.IsAuthorised(Request.Headers, sessionToken, $"{TypeName}s", RightType.UPDATE))
            {
                return(StatusCode(HttpStatusCode.Forbidden));
            }

            if ((zoneId != null && zoneId.Length != 1) || (contextId != null && contextId.Length != 1))
            {
                return(BadRequest($"Request failed for object {TypeName} as Zone and/or Context are invalid."));
            }

            RequestParameter[]     requestParameters      = GetQueryParameters(Request);
            MultipleUpdateResponse multipleUpdateResponse = service.Update(
                obj,
                zoneId?[0],
                contextId?[0],
                requestParameters);
            updateResponseType updateResponse =
                MapperFactory.CreateInstance <MultipleUpdateResponse, updateResponseType>(multipleUpdateResponse);

            return(Ok(updateResponse));
        }
示例#3
0
        public virtual IHttpActionResult Head(
            [MatrixParameter] string[] zoneId    = null,
            [MatrixParameter] string[] contextId = null)
        {
            if (!AuthenticationService.VerifyAuthenticationHeader(Request.Headers, out string sessionToken))
            {
                return(Unauthorized());
            }

            // Check ACLs and return StatusCode(HttpStatusCode.Forbidden) if appropriate.
            if (!AuthorisationService.IsAuthorised(Request.Headers, sessionToken, $"{TypeName}s", RightType.QUERY))
            {
                return(StatusCode(HttpStatusCode.Forbidden));
            }

            if (!HttpUtils.ValidatePagingParameters(Request.Headers, out string errorMessage))
            {
                return(BadRequest(errorMessage));
            }

            if ((zoneId != null && zoneId.Length != 1) || (contextId != null && contextId.Length != 1))
            {
                return(BadRequest($"Request failed for object {TypeName} as Zone and/or Context are invalid."));
            }

            IHttpActionResult result;

            try
            {
                result = GetAll(zoneId?[0], contextId?[0]).ClearContent();

                if (Service is ISupportsChangesSince supportsChangesSince)
                {
                    result = result.AddHeader(
                        "changesSinceMarker",
                        supportsChangesSince.ChangesSinceMarker ?? string.Empty);
                }
            }
            catch (ArgumentException e)
            {
                result = BadRequest(
                    $"One or more parameters of the GET request (associated with the HEAD request) are invalid.\n{e.Message}");
            }
            catch (QueryException e)
            {
                result = BadRequest($"HEAD request failed for object {TypeName}.\n{e.Message}");
            }
            catch (ContentTooLargeException)
            {
                result = StatusCode(HttpStatusCode.RequestEntityTooLarge);
            }
            catch (Exception e)
            {
                result = InternalServerError(e);
            }

            return(result);
        }
示例#4
0
        /// <summary>
        /// <see cref="IProvider{TTSingle,TMultiple,TPrimaryKey}.Get(TPrimaryKey, string[], string[])">Get</see>
        /// </summary>
        public virtual IHttpActionResult Get(
            [FromUri(Name = "id")] string refId,
            [MatrixParameter] string[] zoneId    = null,
            [MatrixParameter] string[] contextId = null)
        {
            if (!AuthenticationService.VerifyAuthenticationHeader(Request.Headers, out string sessionToken))
            {
                return(Unauthorized());
            }

            // Check ACLs and return StatusCode(HttpStatusCode.Forbidden) if appropriate.
            if (!AuthorisationService.IsAuthorised(Request.Headers, sessionToken, $"{TypeName}s", RightType.QUERY))
            {
                return(StatusCode(HttpStatusCode.Forbidden));
            }

            if (HttpUtils.HasPagingHeaders(Request.Headers))
            {
                return(StatusCode(HttpStatusCode.MethodNotAllowed));
            }

            if ((zoneId != null && zoneId.Length != 1) || (contextId != null && contextId.Length != 1))
            {
                return(BadRequest($"Request failed for object {TypeName} as Zone and/or Context are invalid."));
            }

            IHttpActionResult result;

            try
            {
                RequestParameter[] requestParameters = GetQueryParameters(Request);
                TSingle            obj = Service.Retrieve(refId, zoneId?[0], contextId?[0], requestParameters);

                if (obj == null)
                {
                    result = StatusCode(HttpStatusCode.NoContent);
                }
                else
                {
                    result = Ok(obj);
                }
            }
            catch (ArgumentException e)
            {
                result = BadRequest($"Invalid argument: id={refId}.\n{e.Message}");
            }
            catch (QueryException e)
            {
                result = BadRequest($"Request failed for object {TypeName} with ID of {refId}.\n{e.Message}");
            }
            catch (Exception e)
            {
                result = InternalServerError(e);
            }

            return(result);
        }
示例#5
0
        /// <summary>
        /// <see cref="IProvider{TTSingle,TMultiple,TPrimaryKey}.Put(TPrimaryKey, TTSingle, string[], string[])">Put</see>
        /// </summary>
        public virtual IHttpActionResult Put(
            [FromUri(Name = "id")] string refId,
            TSingle obj,
            [MatrixParameter] string[] zoneId    = null,
            [MatrixParameter] string[] contextId = null)
        {
            if (!AuthenticationService.VerifyAuthenticationHeader(Request.Headers, out string sessionToken))
            {
                return(Unauthorized());
            }

            // Check ACLs and return StatusCode(HttpStatusCode.Forbidden) if appropriate.
            if (!AuthorisationService.IsAuthorised(Request.Headers, sessionToken, $"{TypeName}s", RightType.UPDATE))
            {
                return(StatusCode(HttpStatusCode.Forbidden));
            }

            if (string.IsNullOrWhiteSpace(refId) || obj == null || !refId.Equals(obj.RefId))
            {
                return(BadRequest(
                           "The refId in the update request does not match the SIF identifier of the object provided."));
            }

            if ((zoneId != null && zoneId.Length != 1) || (contextId != null && contextId.Length != 1))
            {
                return(BadRequest($"Request failed for object {TypeName} as Zone and/or Context are invalid."));
            }

            IHttpActionResult result;

            try
            {
                RequestParameter[] requestParameters = GetQueryParameters(Request);
                Service.Update(obj, zoneId?[0], contextId?[0], requestParameters);
                result = StatusCode(HttpStatusCode.NoContent);
            }
            catch (ArgumentException e)
            {
                result = BadRequest($"Object to update of type {TypeName} is invalid.\n{e.Message}");
            }
            catch (NotFoundException e)
            {
                result = this.NotFound($"Object {TypeName} with ID of {refId} not found.\n{e.Message}");
            }
            catch (UpdateException e)
            {
                result = BadRequest($"Request failed for object {TypeName} with ID of {refId}.\n{e.Message}");
            }
            catch (Exception e)
            {
                result = InternalServerError(e);
            }

            return(result);
        }
        public void SetUp()
        {
            _clientId    = "zzzzz";
            _authId      = "xxxxx";
            _startDate   = "2011-03-17";
            _startTime   = "12:30";
            _expireafter = "3600000";
            _history     = "http://domain.com/video/history/" + _authId;
            _responseXml = XmlHelper.Create(_authId, _startDate, _startTime, _expireafter, _history);

            _webServiceHelper = new FakeWebServiceHelper(_responseXml);
            _service          = new AuthorisationService(_webServiceHelper);
            _processor        = new AuthorisationProcessor(_service);
        }
示例#7
0
        /// <summary>
        /// <see cref="IProvider{TTSingle,TMultiple,TPrimaryKey}.Delete(TPrimaryKey, string[], string[])">Delete</see>
        /// </summary>
        public virtual IHttpActionResult Delete(
            [FromUri(Name = "id")] string refId,
            [MatrixParameter] string[] zoneId    = null,
            [MatrixParameter] string[] contextId = null)
        {
            if (!AuthenticationService.VerifyAuthenticationHeader(Request.Headers, out string sessionToken))
            {
                return(Unauthorized());
            }

            // Check ACLs and return StatusCode(HttpStatusCode.Forbidden) if appropriate.
            if (!AuthorisationService.IsAuthorised(Request.Headers, sessionToken, $"{TypeName}s", RightType.DELETE))
            {
                return(StatusCode(HttpStatusCode.Forbidden));
            }

            if ((zoneId != null && zoneId.Length != 1) || (contextId != null && contextId.Length != 1))
            {
                return(BadRequest($"Request failed for object {TypeName} as Zone and/or Context are invalid."));
            }

            IHttpActionResult result;

            try
            {
                RequestParameter[] requestParameters = GetQueryParameters(Request);
                Service.Delete(refId, zoneId?[0], contextId?[0], requestParameters);
                result = StatusCode(HttpStatusCode.NoContent);
            }
            catch (ArgumentException e)
            {
                result = BadRequest($"Invalid argument: id={refId}.\n{e.Message}");
            }
            catch (DeleteException e)
            {
                result = BadRequest($"Request failed for object {TypeName} with ID of {refId}.\n{e.Message}");
            }
            catch (NotFoundException e)
            {
                result = this.NotFound($"Object {TypeName} with ID of {refId} not found.\n{e.Message}");
            }
            catch (Exception e)
            {
                result = InternalServerError(e);
            }

            return(result);
        }
示例#8
0
        public void test_startdate_expireafter_history()
        {
            var authId = "xxxxx";

            string startDate   = "2011-03-17";
            string startTime   = "12:30";
            string expireafter = "3600000";
            string history     = "http://domain.com/video/history/" + authId;
            string xml         = XmlHelper.Create(authId, startDate, startTime, expireafter, history);

            var fakeWebServiceHelper = new FakeWebServiceHelper(xml);
            var service = new AuthorisationService(fakeWebServiceHelper);
            var auth    = service.RequestAuthorisation(authId);

            Assert.That(auth.id, Is.EqualTo(authId));
            Assert.That(auth.start[0].date, Is.EqualTo(startDate));
            Assert.That(auth.start[0].time, Is.EqualTo(startTime));
            Assert.That(auth.expireafter, Is.EqualTo(expireafter));
            Assert.That(auth.history[0].href, Is.EqualTo(history));
        }
示例#9
0
        /// <summary>
        /// <see cref="IProvider{TTSingle,TMultiple,TPrimaryKey}.Delete(deleteRequestType, string[], string[])">Delete</see>
        /// </summary>
        public virtual IHttpActionResult Delete(
            deleteRequestType deleteRequest,
            [MatrixParameter] string[] zoneId    = null,
            [MatrixParameter] string[] contextId = null)
        {
            if (!AuthenticationService.VerifyAuthenticationHeader(Request.Headers, out string sessionToken))
            {
                return(Unauthorized());
            }

            // Check ACLs and return StatusCode(HttpStatusCode.Forbidden) if appropriate.
            if (!AuthorisationService.IsAuthorised(Request.Headers, sessionToken, $"{TypeName}s", RightType.DELETE))
            {
                return(StatusCode(HttpStatusCode.Forbidden));
            }

            if ((zoneId != null && zoneId.Length != 1) || (contextId != null && contextId.Length != 1))
            {
                return(BadRequest($"Request failed for object {TypeName} as Zone and/or Context are invalid."));
            }

            ICollection <deleteStatus> deleteStatuses = new List <deleteStatus>();

            try
            {
                foreach (deleteIdType deleteId in deleteRequest.deletes)
                {
                    var status = new deleteStatus
                    {
                        id = deleteId.id
                    };

                    try
                    {
                        RequestParameter[] requestParameters = GetQueryParameters(Request);
                        Service.Delete(deleteId.id, zoneId?[0], contextId?[0], requestParameters);
                        status.statusCode = ((int)HttpStatusCode.NoContent).ToString();
                    }
                    catch (ArgumentException e)
                    {
                        status.error = ProviderUtils.CreateError(
                            HttpStatusCode.BadRequest,
                            TypeName,
                            $"Invalid argument: id={deleteId.id}.\n{e.Message}");
                        status.statusCode = ((int)HttpStatusCode.BadRequest).ToString();
                    }
                    catch (DeleteException e)
                    {
                        status.error = ProviderUtils.CreateError(
                            HttpStatusCode.BadRequest,
                            TypeName,
                            $"Request failed for object {TypeName} with ID of {deleteId.id}.\n{e.Message}");
                        status.statusCode = ((int)HttpStatusCode.BadRequest).ToString();
                    }
                    catch (NotFoundException e)
                    {
                        status.error = ProviderUtils.CreateError(
                            HttpStatusCode.NotFound,
                            TypeName,
                            $"Object {TypeName} with ID of {deleteId.id} not found.\n{e.Message}");
                        status.statusCode = ((int)HttpStatusCode.NotFound).ToString();
                    }
                    catch (Exception e)
                    {
                        status.error = ProviderUtils.CreateError(
                            HttpStatusCode.InternalServerError,
                            TypeName,
                            $"Request failed for object {TypeName} with ID of {deleteId.id}.\n{e.Message}");
                        status.statusCode = ((int)HttpStatusCode.InternalServerError).ToString();
                    }

                    deleteStatuses.Add(status);
                }
            }
            catch (Exception)
            {
                // Need to ignore exceptions otherwise it would not be possible to return status records of processed objects.
            }

            var deleteResponse = new deleteResponseType {
                deletes = deleteStatuses.ToArray()
            };

            return(Ok(deleteResponse));
        }
示例#10
0
        /// <summary>
        /// <see cref="IProvider{TTSingle,TMultiple,TPrimaryKey}.Get(string, string, string, string, string, string, string[], string[])">Get</see>
        /// </summary>
        public virtual IHttpActionResult Get(
            string object1,
            [FromUri(Name = "id1")] string refId1,
            string object2 = null,
            [FromUri(Name = "id2")] string refId2 = null,
            string object3 = null,
            [FromUri(Name = "id3")] string refId3 = null,
            [MatrixParameter] string[] zoneId     = null,
            [MatrixParameter] string[] contextId  = null)
        {
            if (!AuthenticationService.VerifyAuthenticationHeader(Request.Headers, out string sessionToken))
            {
                return(Unauthorized());
            }

            string serviceName;

            if (object3 != null)
            {
                serviceName = $"{object1}/{{}}/{object2}/{{}}/{object3}/{{}}/{TypeName}s";
            }
            else if (object2 != null)
            {
                serviceName = $"{object1}/{{}}/{object2}/{{}}/{TypeName}s";
            }
            else
            {
                serviceName = $"{object1}/{{}}/{TypeName}s";
            }

            // Check ACLs and return StatusCode(HttpStatusCode.Forbidden) if appropriate.
            if (!AuthorisationService.IsAuthorised(Request.Headers, sessionToken, serviceName, RightType.QUERY))
            {
                return(StatusCode(HttpStatusCode.Forbidden));
            }

            if (!HttpUtils.ValidatePagingParameters(Request.Headers, out string errorMessage))
            {
                return(BadRequest(errorMessage));
            }

            if ((zoneId != null && zoneId.Length != 1) || (contextId != null && contextId.Length != 1))
            {
                return(BadRequest($"Request failed for object {TypeName} as Zone and/or Context are invalid."));
            }

            IHttpActionResult result;

            try
            {
                IList <EqualCondition> conditions =
                    new List <EqualCondition>()
                {
                    new EqualCondition()
                    {
                        Left = object1, Right = refId1
                    }
                };

                if (!string.IsNullOrWhiteSpace(object2))
                {
                    conditions.Add(new EqualCondition()
                    {
                        Left = object2, Right = refId2
                    });

                    if (!string.IsNullOrWhiteSpace(object3))
                    {
                        conditions.Add(new EqualCondition()
                        {
                            Left = object3, Right = refId3
                        });
                    }
                }

                uint?navigationPage     = HttpUtils.GetNavigationPage(Request.Headers);
                uint?navigationPageSize = HttpUtils.GetNavigationPageSize(Request.Headers);
                RequestParameter[] requestParameters = GetQueryParameters(Request);
                TMultiple          items             = Service.Retrieve(
                    conditions,
                    navigationPage,
                    navigationPageSize,
                    zoneId?[0],
                    contextId?[0],
                    requestParameters);

                if (items == null)
                {
                    result = StatusCode(HttpStatusCode.NoContent);
                }
                else
                {
                    result = Ok(items);
                }
            }
            catch (ArgumentException e)
            {
                result = BadRequest($"One or more conditions are invalid.\n{e.Message}");
            }
            catch (QueryException e)
            {
                result = BadRequest($"Service Path GET request failed for object {TypeName}.\n{e.Message}");
            }
            catch (ContentTooLargeException)
            {
                result = StatusCode(HttpStatusCode.RequestEntityTooLarge);
            }
            catch (Exception e)
            {
                result = InternalServerError(e);
            }

            return(result);
        }
示例#11
0
        /// <summary>
        /// <see cref="IProvider{TTSingle,TMultiple,TPrimaryKey}.Get(TTSingle, string, string[], string[])">Get</see>
        /// </summary>
        public virtual IHttpActionResult Get(
            TSingle obj,
            string changesSinceMarker            = null,
            [MatrixParameter] string[] zoneId    = null,
            [MatrixParameter] string[] contextId = null)
        {
            if (!AuthenticationService.VerifyAuthenticationHeader(Request.Headers, out string sessionToken))
            {
                return(Unauthorized());
            }

            // Check ACLs and return StatusCode(HttpStatusCode.Forbidden) if appropriate.
            if (!AuthorisationService.IsAuthorised(Request.Headers, sessionToken, $"{TypeName}s", RightType.QUERY))
            {
                return(StatusCode(HttpStatusCode.Forbidden));
            }

            if (!HttpUtils.ValidatePagingParameters(Request.Headers, out string errorMessage))
            {
                return(BadRequest(errorMessage));
            }

            if ((zoneId != null && zoneId.Length != 1) || (contextId != null && contextId.Length != 1))
            {
                return(BadRequest($"Request failed for object {TypeName} as Zone and/or Context are invalid."));
            }

            IHttpActionResult result;

            try
            {
                if (obj == null)
                {
                    result = changesSinceMarker == null
                        ? GetAll(zoneId?[0], contextId?[0])
                        : GetChangesSince(changesSinceMarker, zoneId?[0], contextId?[0]);
                }
                else
                {
                    result = GetQueryByExample(obj, zoneId?[0], contextId?[0]);
                }
            }
            catch (ArgumentException e)
            {
                result = BadRequest($"One or more parameters of the GET request are invalid.\n{e.Message}");
            }
            catch (QueryException e)
            {
                result = BadRequest($"GET request failed for object {TypeName}.\n{e.Message}");
            }
            catch (ContentTooLargeException)
            {
                result = StatusCode(HttpStatusCode.RequestEntityTooLarge);
            }
            catch (Exception e)
            {
                result = InternalServerError(e);
            }

            return(result);
        }
示例#12
0
        /// <summary>
        /// <see cref="IProvider{TTSingle,TMultiple,TPrimaryKey}.Post(TTSingle, string[], string[])">Post</see>
        /// </summary>
        public virtual IHttpActionResult Post(
            TSingle obj,
            [MatrixParameter] string[] zoneId    = null,
            [MatrixParameter] string[] contextId = null)
        {
            if (!AuthenticationService.VerifyAuthenticationHeader(Request.Headers, out string sessionToken))
            {
                return(Unauthorized());
            }

            // Check ACLs and return StatusCode(HttpStatusCode.Forbidden) if appropriate.
            if (!AuthorisationService.IsAuthorised(Request.Headers, sessionToken, $"{TypeName}s", RightType.CREATE))
            {
                return(StatusCode(HttpStatusCode.Forbidden));
            }

            if ((zoneId != null && zoneId.Length != 1) || (contextId != null && contextId.Length != 1))
            {
                return(BadRequest($"Request failed for object {TypeName} as Zone and/or Context are invalid."));
            }

            IHttpActionResult result;

            try
            {
                bool hasAdvisoryId   = !string.IsNullOrWhiteSpace(obj.RefId);
                bool?mustUseAdvisory = HttpUtils.GetMustUseAdvisory(Request.Headers);

                if (mustUseAdvisory.HasValue)
                {
                    if (mustUseAdvisory.Value && !hasAdvisoryId)
                    {
                        result = BadRequest(
                            $"Request failed for object {TypeName} as object ID is not provided, but mustUseAdvisory is true.");
                    }
                    else
                    {
                        RequestParameter[] requestParameters = GetQueryParameters(Request);
                        TSingle            createdObject     =
                            Service.Create(obj, mustUseAdvisory, zoneId?[0], contextId?[0], requestParameters);
                        string uri = Url.Link("DefaultApi", new { controller = TypeName, id = createdObject.RefId });
                        result = Created(uri, createdObject);
                    }
                }
                else
                {
                    RequestParameter[] requestParameters = GetQueryParameters(Request);
                    TSingle            createdObject     = Service.Create(obj, null, zoneId?[0], contextId?[0], requestParameters);
                    string             uri = Url.Link("DefaultApi", new { controller = TypeName, id = createdObject.RefId });
                    result = Created(uri, createdObject);
                }
            }
            catch (AlreadyExistsException)
            {
                result = Conflict();
            }
            catch (ArgumentException e)
            {
                result = BadRequest($"Object to create of type {TypeName} is invalid.\n{e.Message}");
            }
            catch (CreateException e)
            {
                result = BadRequest($"Request failed for object {TypeName}.\n{e.Message}");
            }
            catch (RejectedException e)
            {
                result = this.NotFound(
                    $"Create request rejected for object {TypeName} with ID of {obj.RefId}.\n{e.Message}");
            }
            catch (QueryException e)
            {
                result = BadRequest($"Request failed for object {TypeName}.\n{e.Message}");
            }
            catch (Exception e)
            {
                result = InternalServerError(e);
            }

            return(result);
        }
        /// <summary>
        /// <see cref="Provider{TSingle, TMultiple}.Post(TMultiple, string[], string[])">Post</see>
        /// </summary>
        public override IHttpActionResult Post(
            List <T> objs,
            [MatrixParameter] string[] zoneId    = null,
            [MatrixParameter] string[] contextId = null)
        {
            if (!AuthenticationService.VerifyAuthenticationHeader(Request.Headers, out string sessionToken))
            {
                return(Unauthorized());
            }

            // Check ACLs and return StatusCode(HttpStatusCode.Forbidden) if appropriate.
            if (!AuthorisationService.IsAuthorised(Request.Headers, sessionToken, $"{TypeName}s", RightType.CREATE))
            {
                return(StatusCode(HttpStatusCode.Forbidden));
            }

            if ((zoneId != null && zoneId.Length != 1) || (contextId != null && contextId.Length != 1))
            {
                return(BadRequest($"Request failed for object {TypeName} as Zone and/or Context are invalid."));
            }

            ICollection <createType> createStatuses = new List <createType>();

            try
            {
                bool?mustUseAdvisory = HttpUtils.GetMustUseAdvisory(Request.Headers);

                foreach (T obj in objs)
                {
                    bool hasAdvisoryId = !string.IsNullOrWhiteSpace(obj.RefId);
                    var  status        = new createType
                    {
                        advisoryId = (hasAdvisoryId ? obj.RefId : null)
                    };

                    try
                    {
                        if (mustUseAdvisory.HasValue)
                        {
                            if (mustUseAdvisory.Value && !hasAdvisoryId)
                            {
                                status.error = ProviderUtils.CreateError(
                                    HttpStatusCode.BadRequest,
                                    TypeName,
                                    "Create request failed as object ID is not provided, but mustUseAdvisory is true.");
                                status.statusCode = ((int)HttpStatusCode.BadRequest).ToString();
                            }
                            else
                            {
                                status.id         = Service.Create(obj, mustUseAdvisory, zoneId?[0], contextId?[0]).RefId;
                                status.statusCode = ((int)HttpStatusCode.Created).ToString();
                            }
                        }
                        else
                        {
                            status.id         = Service.Create(obj, null, zoneId?[0], contextId?[0]).RefId;
                            status.statusCode = ((int)HttpStatusCode.Created).ToString();
                        }
                    }
                    catch (AlreadyExistsException e)
                    {
                        status.error = ProviderUtils.CreateError(
                            HttpStatusCode.Conflict,
                            TypeName,
                            $"Object {TypeName} with ID of {obj.RefId} already exists.\n{e.Message}");
                        status.statusCode = ((int)HttpStatusCode.Conflict).ToString();
                    }
                    catch (ArgumentException e)
                    {
                        status.error = ProviderUtils.CreateError(
                            HttpStatusCode.BadRequest,
                            TypeName,
                            $"Object to create of type {TypeName}" + (hasAdvisoryId ? $" with ID of {obj.RefId}" : "") + $" is invalid.\n {e.Message}");
                        status.statusCode = ((int)HttpStatusCode.BadRequest).ToString();
                    }
                    catch (CreateException e)
                    {
                        status.error = ProviderUtils.CreateError(
                            HttpStatusCode.BadRequest,
                            TypeName,
                            $"Request failed for object {TypeName}" + (hasAdvisoryId ? $" with ID of {obj.RefId}" : "") + $".\n{e.Message}");
                        status.statusCode = ((int)HttpStatusCode.BadRequest).ToString();
                    }
                    catch (RejectedException e)
                    {
                        status.error = ProviderUtils.CreateError(
                            HttpStatusCode.NotFound,
                            TypeName,
                            $"Create request rejected for object {TypeName} with ID of {obj.RefId}.\n{e.Message}");
                        status.statusCode = ((int)HttpStatusCode.Conflict).ToString();
                    }
                    catch (Exception e)
                    {
                        status.error = ProviderUtils.CreateError(
                            HttpStatusCode.InternalServerError,
                            TypeName,
                            $"Request failed for object {TypeName}" + (hasAdvisoryId ? $" with ID of {obj.RefId}" : "") + $".\n{e.Message}");
                        status.statusCode = ((int)HttpStatusCode.InternalServerError).ToString();
                    }

                    createStatuses.Add(status);
                }
            }
            catch (Exception)
            {
                // Need to ignore exceptions otherwise it would not be possible to return status records of processed objects.
            }

            var createResponse = new createResponseType {
                creates = createStatuses.ToArray()
            };

            return(Ok(createResponse));
        }
        /// <summary>
        /// <see cref="Provider{TSingle, TMultiple}.Put(TMultiple, string[], string[])">Put</see>
        /// </summary>
        public override IHttpActionResult Put(
            List <T> objs,
            [MatrixParameter] string[] zoneId    = null,
            [MatrixParameter] string[] contextId = null)
        {
            if (!AuthenticationService.VerifyAuthenticationHeader(Request.Headers, out string sessionToken))
            {
                return(Unauthorized());
            }

            // Check ACLs and return StatusCode(HttpStatusCode.Forbidden) if appropriate.
            if (!AuthorisationService.IsAuthorised(Request.Headers, sessionToken, $"{TypeName}s", RightType.CREATE))
            {
                return(StatusCode(HttpStatusCode.Forbidden));
            }

            if ((zoneId != null && zoneId.Length != 1) || (contextId != null && contextId.Length != 1))
            {
                return(BadRequest($"Request failed for object {TypeName} as Zone and/or Context are invalid."));
            }

            ICollection <updateType> updateStatuses = new List <updateType>();

            try
            {
                foreach (T obj in objs)
                {
                    var status = new updateType
                    {
                        id = obj.RefId
                    };

                    try
                    {
                        Service.Update(obj, (zoneId?[0]), (contextId?[0]));
                        status.statusCode = ((int)HttpStatusCode.NoContent).ToString();
                    }
                    catch (ArgumentException e)
                    {
                        status.error = ProviderUtils.CreateError(
                            HttpStatusCode.BadRequest,
                            TypeName,
                            $"Object to update of type {TypeName} is invalid.\n{e.Message}");
                        status.statusCode = ((int)HttpStatusCode.BadRequest).ToString();
                    }
                    catch (NotFoundException e)
                    {
                        status.error = ProviderUtils.CreateError(
                            HttpStatusCode.NotFound,
                            TypeName,
                            $"Object {TypeName} with ID of {obj.RefId} not found.\n{e.Message}");
                        status.statusCode = ((int)HttpStatusCode.NotFound).ToString();
                    }
                    catch (UpdateException e)
                    {
                        status.error = ProviderUtils.CreateError(
                            HttpStatusCode.BadRequest,
                            TypeName,
                            $"Request failed for object {TypeName} with ID of {obj.RefId}.\n{e.Message}");
                        status.statusCode = ((int)HttpStatusCode.BadRequest).ToString();
                    }
                    catch (Exception e)
                    {
                        status.error = ProviderUtils.CreateError(
                            HttpStatusCode.InternalServerError,
                            TypeName,
                            $"Request failed for object {TypeName} with ID of {obj.RefId}.\n{e.Message}");
                        status.statusCode = ((int)HttpStatusCode.InternalServerError).ToString();
                    }

                    updateStatuses.Add(status);
                }
            }
            catch (Exception)
            {
                // Need to ignore exceptions otherwise it would not be possible to return status records of processed objects.
            }

            var updateResponse = new updateResponseType {
                updates = updateStatuses.ToArray()
            };

            return(Ok(updateResponse));
        }