Ejemplo n.º 1
0
        public KeyExpression(ResourceContainer container, ResourceType resourceType, IDictionary <string, object> properties)
            : base(null)
        {
            // populate key and ETag from properties
            List <NodeProperty> keyProperties = resourceType.Key.Properties.ToList();

            _properties        = new PropertyExpression[keyProperties.Count];
            _values            = new ConstantExpression[keyProperties.Count];
            _include           = new bool[keyProperties.Count];
            _resourceType      = resourceType;
            _resourceContainer = container; // originally, this would not happen if using constructor without type

            for (int i = 0; i < keyProperties.Count; i++)
            {
                NodeProperty property = keyProperties[i];
                _properties[i] = new PropertyExpression(property);
                _values[i]     = new ConstantExpression(new NodeValue(properties[property.Name], property.Type));
                _include[i]    = true;
            }

            if (resourceType.Properties.Any(p => p.Facets.ConcurrencyModeFixed))
            {
                ETag = ConcurrencyUtil.ConstructETag(container, properties);
            }
            else
            {
                ETag = null;
            }

            this.KnownPropertyValues = properties;
        }
Ejemplo n.º 2
0
        protected override void Verify()
        {
            if (!Applies(Response))
            {
                return;
            }

            // build a common payload for the insert
            //
            CommonPayload insertPayload = Response.Request.CommonPayload;

            // get the entity that was inserted
            PayloadObject inserted;

            if (!TryGetSingleObjectFromPayload(insertPayload, out inserted))
            {
                ResponseVerification.LogFailure(Response, new Exception("Insert request payload did not contain a single entity"));
            }

            // determine the type based on what was inserted
            ResourceType type = Response.Workspace.ServiceContainer.ResourceTypes.Single(rt => inserted.Type.Equals(rt.Namespace + "." + rt.Name));

            // get the entity that was returned
            PayloadObject returned;

            if (!TryGetSingleObjectFromPayload(Response.CommonPayload, out returned))
            {
                if (Versioning.Server.SupportsLiveFeatures)
                {
                    string preferHeader;
                    if (Response.Request.Headers.TryGetValue("prefer", out preferHeader) && preferHeader == "return=minimal")
                    {
                        return;
                    }
                }

                ResponseVerification.LogFailure(Response, new Exception("Insert response payload did not contain a single entity"));
            }

            // verify that the inserted and returned entities are equivalent
            VerifyInsertResponse(type, inserted, returned);

            // re-query the entity
            Workspace      workspace    = Response.Workspace;
            AstoriaRequest queryRequest = workspace.CreateRequest();

            if (type.Properties.Any(p => p.Facets.ConcurrencyModeFixed))
            {
                queryRequest.ETagHeaderExpected = true;
            }

            if (type.Key.Properties.Any(p => p.Type == Clr.Types.DateTime))
            {
                // this will blow up for MEST, but we don't currently have any datetime key + MEST types
                ResourceContainer container = Response.Workspace.ServiceContainer.ResourceContainers.Single(rc => !(rc is ServiceOperation) && rc.ResourceTypes.Contains(type));
                queryRequest.Query = ContainmentUtil.BuildCanonicalQuery(ConcurrencyUtil.ConstructKey(container, returned));
            }
            else
            {
                queryRequest.URI = Uri.UnescapeDataString(returned.AbsoluteUri);
                if (queryRequest.URI.Contains("E+"))
                {
                    queryRequest.URI = queryRequest.URI.Replace("E+", "E");
                }
                if (queryRequest.URI.Contains("e+"))
                {
                    queryRequest.URI = queryRequest.URI.Replace("e+", "e");
                }
            }

            AstoriaResponse queryResponse = queryRequest.GetResponse();

            if (queryResponse.ActualStatusCode == HttpStatusCode.BadRequest)
            {
                // try it as a filter instead (possibly caused by the URI being too long)
                // this will blow up for MEST
                ResourceContainer container = Response.Workspace.ServiceContainer.ResourceContainers
                                              .Single(rc => !(rc is ServiceOperation) && rc.ResourceTypes.Contains(type));
                KeyExpression key = ConcurrencyUtil.ConstructKey(container, returned);
                queryRequest  = workspace.CreateRequest(Query.From(Exp.Variable(container)).Where(key.Predicate));
                queryResponse = queryRequest.GetResponse();
            }
            queryResponse.Verify();

            // get the entity from the query
            PayloadObject queried;

            if (!TryGetSingleObjectFromPayload(queryResponse.CommonPayload, out queried))
            {
                ResponseVerification.LogFailure(queryResponse, new Exception("Query response payload did not contain a single entity"));
            }

            // ensure that the entity did not change between the insert and the re-query
            VerifyQueryResponse(type, returned, queried);
        }