Пример #1
0
        private void AssertAttribute <TPropertyType, TTokenType>(IResourceTypeRegistration reg, string attributeName,
                                                                 JToken tokenToSet, TPropertyType expectedPropertyValue, TTokenType expectedTokenAfterSet, Func <AttributeGrabBag, TPropertyType> getPropertyFunc)
        {
            var grabBag = InitializeGrabBag();

            var field     = reg.GetFieldByName(attributeName);
            var attribute = (ResourceTypeAttribute)field;

            attribute.JsonKey.Should().Be(attributeName);

            attribute.SetValue(grabBag, tokenToSet);
            var propertyValueAfterSet = getPropertyFunc(grabBag);

            propertyValueAfterSet.Should().Be(expectedPropertyValue);

            var convertedToken = attribute.GetValue(grabBag);

            if (expectedTokenAfterSet == null)
            {
                convertedToken.Should().BeNull();
            }
            else
            {
                var convertedTokenValue = convertedToken.Value <TTokenType>();
                convertedTokenValue.Should().Be(expectedTokenAfterSet);
            }
        }
Пример #2
0
        private void AssertAttributeHelper(IResourceTypeRegistration reg, string attributeName,
                                           JToken tokenToSet, Action <AttributeGrabBag> testPropertyValueAfterSet,
                                           Action <JToken> testTokenAfterSetAndGet)
        {
            var grabBag = InitializeGrabBag();

            var field     = reg.GetFieldByName(attributeName);
            var attribute = (ResourceTypeAttribute)field;

            attribute.JsonKey.Should().Be(attributeName);

            attribute.SetValue(grabBag, tokenToSet);
            testPropertyValueAfterSet(grabBag);

            var convertedToken = attribute.GetValue(grabBag);

            testTokenAfterSetAndGet(convertedToken);
        }
Пример #3
0
        private Expression GetPredicate(string filterField, IResourceTypeRegistration registration, ParameterExpression param, string queryValue)
        {
            if (filterField == "id")
            {
                return(GetPredicateBodyForProperty(registration.IdProperty, queryValue, param));
            }

            var resourceTypeField = registration.GetFieldByName(filterField);

            if (resourceTypeField == null)
            {
                throw JsonApiException.CreateForBadRequest(
                          string.Format("No attribute {0} exists on the specified type.", filterField));
            }

            if (string.IsNullOrWhiteSpace(queryValue))
            {
                queryValue = null;
            }

            // See if it is a field property
            var fieldModelProperty = resourceTypeField as ResourceTypeAttribute;

            if (fieldModelProperty != null)
            {
                return(GetPredicateBodyForField(fieldModelProperty, queryValue, param));
            }

            // See if it is a relationship property
            var relationshipModelProperty = resourceTypeField as ResourceTypeRelationship;

            if (relationshipModelProperty != null)
            {
                return(GetPredicateBodyForRelationship(relationshipModelProperty, queryValue, param));
            }

            throw JsonApiException.CreateForBadRequest(
                      string.Format("The attribute {0} is unsupported for filtering.", filterField));
        }
        /// <summary>
        /// Merges the field values of the given resource object into the materialized object
        /// </summary>
        /// <param name="resourceObject"></param>
        /// <param name="material"></param>
        /// <param name="registration"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        /// <exception cref="DeserializationException">Thrown when a semantically incorrect part of the document is encountered</exception>
        protected virtual async Task MergeFieldsIntoProperties(IResourceObject resourceObject, object material,
                                                               IResourceTypeRegistration registration, CancellationToken cancellationToken)
        {
            foreach (var attributeValue in resourceObject.Attributes)
            {
                var attribute = registration.GetFieldByName(attributeValue.Key) as ResourceTypeAttribute;
                if (attribute == null)
                {
                    continue;
                }
                attribute.SetValue(material, attributeValue.Value);
            }

            foreach (var relationshipValue in resourceObject.Relationships)
            {
                var linkage = relationshipValue.Value.Linkage;

                var typeRelationship = registration.GetFieldByName(relationshipValue.Key) as ResourceTypeRelationship;
                if (typeRelationship == null)
                {
                    continue;
                }

                if (typeRelationship.IsToMany)
                {
                    if (linkage == null)
                    {
                        throw new DeserializationException("Missing linkage for to-many relationship",
                                                           "Expected an array for to-many linkage, but no linkage was specified.", "/data/relationships/" + relationshipValue.Key);
                    }

                    if (!linkage.IsToMany)
                    {
                        throw new DeserializationException("Invalid linkage for to-many relationship",
                                                           "Expected an array for to-many linkage.",
                                                           "/data/relationships/" + relationshipValue.Key + "/data");
                    }

                    // TODO: One query per related object is going to be slow. At the very least, we should be able to group the queries by type
                    var newCollection = new List <object>();
                    foreach (var resourceIdentifier in linkage.Identifiers)
                    {
                        var relatedObjectRegistration = _registry.GetRegistrationForResourceTypeName(resourceIdentifier.Type);
                        var relatedObject             = await GetExistingRecord(relatedObjectRegistration, resourceIdentifier.Id, null, cancellationToken);

                        newCollection.Add(relatedObject);
                    }

                    var method = _openSetToManyRelationshipValueMethod.MakeGenericMethod(typeRelationship.RelatedType);
                    method.Invoke(this, new[] { material, newCollection, typeRelationship });
                }
                else
                {
                    if (linkage == null)
                    {
                        throw new DeserializationException("Missing linkage for to-one relationship",
                                                           "Expected an object for to-one linkage, but no linkage was specified.", "/data/relationships/" + relationshipValue.Key);
                    }

                    if (linkage.IsToMany)
                    {
                        throw new DeserializationException("Invalid linkage for to-one relationship",
                                                           "Expected an object or null for to-one linkage",
                                                           "/data/relationships/" + relationshipValue.Key + "/data");
                    }

                    var identifier = linkage.Identifiers.FirstOrDefault();
                    if (identifier == null)
                    {
                        typeRelationship.Property.SetValue(material, null);
                    }
                    else
                    {
                        var relatedObjectRegistration = _registry.GetRegistrationForResourceTypeName(identifier.Type);
                        var relatedObject             =
                            await GetExistingRecord(relatedObjectRegistration, identifier.Id, null, cancellationToken);

                        typeRelationship.Property.SetValue(material, relatedObject);
                    }
                }
            }
        }