Exemplo n.º 1
0
        /// <summary>
        /// Converts a <see cref="ODataResourceValue"/> to a string.
        /// </summary>
        /// <param name="resourceValue">Instance to convert.</param>
        /// <param name="model">Model to be used for validation. User model is optional. The EdmLib core model is expected as a minimum.</param>
        /// <param name="version">Version to be compliant with.</param>
        /// <returns>A string representation of <paramref name="resourceValue"/> to be added.</returns>
        internal static string ConvertToResourceLiteral(ODataResourceValue resourceValue, IEdmModel model, ODataVersion version)
        {
            ExceptionUtils.CheckArgumentNotNull(resourceValue, "resourceValue");
            ExceptionUtils.CheckArgumentNotNull(model, "model");

            StringBuilder builder = new StringBuilder();

            using (TextWriter textWriter = new StringWriter(builder, CultureInfo.InvariantCulture))
            {
                ODataMessageWriterSettings messageWriterSettings = new ODataMessageWriterSettings()
                {
                    Version     = version,
                    Validations = ~ValidationKinds.ThrowOnUndeclaredPropertyForNonOpenType,

                    // Should write instance annotations for the literal
                    ShouldIncludeAnnotation = ODataUtils.CreateAnnotationFilter("*")
                };

                WriteJsonLightLiteral(
                    model,
                    messageWriterSettings,
                    textWriter,
                    (serializer) => serializer.WriteResourceValue(
                        resourceValue, /* resourceValue */
                        null,          /* metadataTypeReference */
                        true,          /* isOpenPropertyType */
                        serializer.CreateDuplicatePropertyNameChecker()));
            }

            return(builder.ToString());
        }
Exemplo n.º 2
0
        /// <summary>
        /// Gets the type name from the given <paramref name="value"/>.
        /// </summary>
        /// <param name="value">The value to get the type name from. This can be an ODataPrimitiveValue, an ODataCollectionValue or a Clr primitive object.</param>
        /// <returns>The type name for the given <paramref name="value"/>.</returns>
        protected static string GetTypeNameFromValue(object value)
        {
            Debug.Assert(value != null, "value != null");

            ODataPrimitiveValue primitiveValue = value as ODataPrimitiveValue;

            if (primitiveValue != null)
            {
                // primitiveValueTypeReference == null means: the EDM type of the primitive value cannot be determined.
                // This could possibly be due to value being an unsigned int.
                // In this case, simply return null because:
                //   - If the property is regular property, the type is not needed since service model knows its exact type.
                //   - If the property is dynamic property, ODL does not support dynamic property containing unsigned int value
                //     since we don't know its underlying type as well as how to serialize it.
                IEdmPrimitiveTypeReference primitiveValueTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(primitiveValue.Value.GetType());
                return(primitiveValueTypeReference == null ? null : primitiveValueTypeReference.FullName());
            }

            ODataEnumValue enumValue = value as ODataEnumValue;

            if (enumValue != null)
            {
                return(enumValue.TypeName);
            }

            ODataResourceValue resourceValue = value as ODataResourceValue;

            if (resourceValue != null)
            {
                return(resourceValue.TypeName);
            }

            ODataCollectionValue collectionValue = value as ODataCollectionValue;

            if (collectionValue != null)
            {
                return(EdmLibraryExtensions.GetCollectionTypeFullName(collectionValue.TypeName));
            }

            IEdmPrimitiveTypeReference primitiveTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(value.GetType());

            if (primitiveTypeReference == null)
            {
                throw new ODataException(Strings.ValidationUtils_UnsupportedPrimitiveType(value.GetType().FullName));
            }

            return(primitiveTypeReference.FullName());
        }
Exemplo n.º 3
0
        /// <summary>
        /// Resolve a type name against the provided <paramref name="model"/>. If not payload type name is specified,
        /// derive the type from the model type (if available).
        /// </summary>
        /// <param name="model">The model to use.</param>
        /// <param name="typeReferenceFromMetadata">The type inferred from the model or null if the model is not a user model.</param>
        /// <param name="resourceValue">The value in question to resolve the type for.</param>
        /// <param name="isOpenPropertyType">True if the type name belongs to an open (dynamic) property.</param>
        /// <param name="writerValidator">The writer validator to use for validation.</param>
        /// <returns>A type for the <paramref name="resourceValue"/> or null if no type name is specified and no metadata is available.</returns>
        internal static IEdmTypeReference ResolveAndValidateTypeForResourceValue(IEdmModel model, IEdmTypeReference typeReferenceFromMetadata,
                                                                                 ODataResourceValue resourceValue, bool isOpenPropertyType, IWriterValidator writerValidator)
        {
            Debug.Assert(model != null, "model != null");
            Debug.Assert(resourceValue != null, "resourceValue != null");

            var typeName = resourceValue.TypeName;

            ValidateIfTypeNameMissing(typeName, model, isOpenPropertyType);

            // It's ok to use "EdmTypeKind.Complex" because the validation will check "IsStructured()".
            IEdmType typeFromValue = typeName == null ? null : ResolveAndValidateTypeName(model, typeName, EdmTypeKind.Complex, true, writerValidator);

            if (typeReferenceFromMetadata != null)
            {
                // It's ok to use "EdmTypeKind.Complex" because the parameter "expectStructuredType" is set to "true".
                writerValidator.ValidateTypeKind(EdmTypeKind.Complex, typeReferenceFromMetadata.TypeKind(), true, typeFromValue);
            }

            return(ResolveTypeFromMetadataAndValue(typeReferenceFromMetadata,
                                                   typeFromValue == null ? null : typeFromValue.ToTypeReference(), writerValidator));
        }
Exemplo n.º 4
0
        public static string ConvertToUriLiteral(object value, ODataVersion version, IEdmModel model)
        {
            if (value == null)
            {
                value = new ODataNullValue();
            }

            if (model == null)
            {
                model = Microsoft.OData.Edm.EdmCoreModel.Instance;
            }

            ODataNullValue nullValue = value as ODataNullValue;

            if (nullValue != null)
            {
                return(ExpressionConstants.KeywordNull);
            }

            ODataResourceValue resourceValue = value as ODataResourceValue;

            if (resourceValue != null)
            {
                return(ODataUriConversionUtils.ConvertToResourceLiteral(resourceValue, model, version));
            }

            ODataCollectionValue collectionValue = value as ODataCollectionValue;

            if (collectionValue != null)
            {
                return(ODataUriConversionUtils.ConvertToUriCollectionLiteral(collectionValue, model, version));
            }

            ODataEnumValue enumValue = value as ODataEnumValue;

            if (enumValue != null)
            {
                return(ODataUriConversionUtils.ConvertToUriEnumLiteral(enumValue, version));
            }

            ODataResourceBase resource = value as ODataResourceBase;

            if (resource != null)
            {
                return(ODataUriConversionUtils.ConvertToUriEntityLiteral(resource, model));
            }

            ODataEntityReferenceLink link = value as ODataEntityReferenceLink;

            if (link != null)
            {
                return(ODataUriConversionUtils.ConvertToUriEntityReferenceLiteral(link, model));
            }

            ODataEntityReferenceLinks links = value as ODataEntityReferenceLinks;

            if (links != null)
            {
                return(ODataUriConversionUtils.ConvertToUriEntityReferencesLiteral(links, model));
            }

            IEnumerable <ODataResourceBase> list = value as IEnumerable <ODataResourceBase>;

            if (list != null)
            {
                return(ODataUriConversionUtils.ConvertToUriEntitiesLiteral(list, model));
            }

            // Try to convert uints to their underlying type first according to the model.
            value = model.ConvertToUnderlyingTypeIfUIntValue(value);

            return(ODataUriConversionUtils.ConvertToUriPrimitiveLiteral(value, version));
        }
Exemplo n.º 5
0
        /// <summary>
        /// Asynchronously writes an instance annotation.
        /// </summary>
        /// <param name="instanceAnnotation">The instance annotation to write.</param>
        /// <param name="ignoreFilter">Whether to ignore the filter in settings.</param>
        /// <param name="propertyName">The name of the property this instance annotation applies tos</param>
        internal async Task WriteInstanceAnnotationAsync(
            ODataInstanceAnnotation instanceAnnotation,
            bool ignoreFilter   = false,
            string propertyName = null)
        {
            string     annotationName  = instanceAnnotation.Name;
            ODataValue annotationValue = instanceAnnotation.Value;

            Debug.Assert(!string.IsNullOrEmpty(annotationName), "annotationName should not be null or empty");
            Debug.Assert(annotationValue != null, "annotationValue should not be null because we use ODataNullValue for null instead");
            Debug.Assert(!(annotationValue is ODataStreamReferenceValue), "!(annotationValue is ODataStreamReferenceValue) -- ODataInstanceAnnotation and InstanceAnnotationCollection will throw if the value is a stream value.");
            Debug.Assert(this.valueSerializer.Model != null, "this.valueSerializer.Model != null");

            if (!ignoreFilter && this.valueSerializer.MessageWriterSettings.ShouldSkipAnnotation(annotationName))
            {
                return;
            }

            IEdmTypeReference expectedType = MetadataUtils.LookupTypeOfTerm(annotationName, this.valueSerializer.Model);

            if (annotationValue is ODataNullValue)
            {
                if (expectedType != null && !expectedType.IsNullable)
                {
                    throw new ODataException(
                              ODataErrorStrings.JsonLightInstanceAnnotationWriter_NullValueNotAllowedForInstanceAnnotation(
                                  annotationName, expectedType.FullName()));
                }

                await this.WriteInstanceAnnotationNameAsync(propertyName, annotationName)
                .ConfigureAwait(false);

                await this.valueSerializer.WriteNullValueAsync()
                .ConfigureAwait(false);

                return;
            }

            // If we didn't find an expected type from looking up the term in the model, treat this value the same way we would for open property values.
            // That is, write the type name (unless its a primitive value with a JSON-native type).  If we did find an expected type, treat the annotation value like a
            // declared property with an expected type. This will still write out the type if the value type is more derived than the declared type, for example.
            bool treatLikeOpenProperty = expectedType == null;

            ODataResourceValue resourceValue = annotationValue as ODataResourceValue;

            if (resourceValue != null)
            {
                IDuplicatePropertyNameChecker duplicatePropertyNameChecker = this.valueSerializer.GetDuplicatePropertyNameChecker();
                await this.WriteInstanceAnnotationNameAsync(propertyName, annotationName)
                .ConfigureAwait(false);

                await this.valueSerializer.WriteResourceValueAsync(resourceValue,
                                                                   expectedType,
                                                                   treatLikeOpenProperty,
                                                                   duplicatePropertyNameChecker).ConfigureAwait(false);

                this.valueSerializer.ReturnDuplicatePropertyNameChecker(duplicatePropertyNameChecker);

                return;
            }

            ODataCollectionValue collectionValue = annotationValue as ODataCollectionValue;

            if (collectionValue != null)
            {
                IEdmTypeReference typeFromCollectionValue = (IEdmCollectionTypeReference)TypeNameOracle.ResolveAndValidateTypeForCollectionValue(
                    this.valueSerializer.Model, expectedType, collectionValue, treatLikeOpenProperty, this.writerValidator);
                string collectionTypeNameToWrite = this.typeNameOracle.GetValueTypeNameForWriting(collectionValue, expectedType, typeFromCollectionValue, treatLikeOpenProperty);
                if (collectionTypeNameToWrite != null)
                {
                    await this.asynchronousODataAnnotationWriter.WriteODataTypePropertyAnnotationAsync(annotationName, collectionTypeNameToWrite)
                    .ConfigureAwait(false);
                }

                await this.WriteInstanceAnnotationNameAsync(propertyName, annotationName)
                .ConfigureAwait(false);

                await this.valueSerializer.WriteCollectionValueAsync(
                    collectionValue,
                    expectedType,
                    typeFromCollectionValue,
                    false /*isTopLevelProperty*/,
                    false /*isInUri*/,
                    treatLikeOpenProperty).ConfigureAwait(false);

                return;
            }

            ODataUntypedValue untypedValue = annotationValue as ODataUntypedValue;

            if (untypedValue != null)
            {
                await this.WriteInstanceAnnotationNameAsync(propertyName, annotationName)
                .ConfigureAwait(false);

                await this.valueSerializer.WriteUntypedValueAsync(untypedValue)
                .ConfigureAwait(false);

                return;
            }

            ODataEnumValue enumValue = annotationValue as ODataEnumValue;

            if (enumValue != null)
            {
                await this.WriteInstanceAnnotationNameAsync(propertyName, annotationName)
                .ConfigureAwait(false);

                await this.valueSerializer.WriteEnumValueAsync(enumValue, expectedType)
                .ConfigureAwait(false);

                return;
            }

            ODataPrimitiveValue primitiveValue = annotationValue as ODataPrimitiveValue;

            Debug.Assert(primitiveValue != null, "Did we add a new subclass of ODataValue?");

            IEdmTypeReference typeFromPrimitiveValue = TypeNameOracle.ResolveAndValidateTypeForPrimitiveValue(primitiveValue);

            string primitiveTypeNameToWrite = this.typeNameOracle.GetValueTypeNameForWriting(primitiveValue, expectedType, typeFromPrimitiveValue, treatLikeOpenProperty);

            if (primitiveTypeNameToWrite != null)
            {
                await this.asynchronousODataAnnotationWriter.WriteODataTypePropertyAnnotationAsync(annotationName, primitiveTypeNameToWrite)
                .ConfigureAwait(false);
            }

            await this.WriteInstanceAnnotationNameAsync(propertyName, annotationName)
            .ConfigureAwait(false);

            await this.valueSerializer.WritePrimitiveValueAsync(primitiveValue.Value, typeFromPrimitiveValue, expectedType)
            .ConfigureAwait(false);
        }