Пример #1
0
        /// <summary>
        /// Converts the object to ODataResource or ODataEntityReferenceLink.
        /// </summary>
        /// <param name="value">The value of the <see cref="UriOperationParameter"/>.</param>
        /// <param name="elementType">The type of the value</param>
        /// <param name="useEntityReference">If true, use entity reference, instead of entity to serialize the parameter.</param>
        /// <returns>The converted result.</returns>
        private object ConvertToEntityValue(object value, Type elementType, bool useEntityReference)
        {
            object valueInODataFormat;

            if (!useEntityReference)
            {
                valueInODataFormat = this.propertyConverter.CreateODataEntry(elementType, value);

                ODataResource entry = (ODataResource)valueInODataFormat;
                if (entry.TypeAnnotation == null ||
                    string.IsNullOrEmpty(entry.TypeAnnotation.TypeName))
                {
                    throw Error.InvalidOperation(Strings.DataServiceException_GeneralError);
                }
            }
            else
            {
                EntityDescriptor resource = this.requestInfo.EntityTracker.GetEntityDescriptor(value);
                Uri link = resource.GetLatestIdentity();
                valueInODataFormat = new ODataEntityReferenceLink()
                {
                    Url = link,
                };
            }

            return(valueInODataFormat);
        }
Пример #2
0
        /// <summary>
        /// Creates an ODataEntry for the given EntityDescriptor and fills in its ODataLib metadata.
        /// </summary>
        /// <param name="entityDescriptor">The entity descriptor.</param>
        /// <param name="serverTypeName">Name of the server type.</param>
        /// <param name="entityType">The client-side entity type.</param>
        /// <param name="clientFormat">The current client format.</param>
        /// <returns>An odata entry with its metadata filled in.</returns>
        internal static ODataEntry CreateODataEntry(EntityDescriptor entityDescriptor, string serverTypeName, ClientTypeAnnotation entityType, DataServiceClientFormat clientFormat)
        {
            ODataEntry entry = new ODataEntry();

            // If the client type name is different from the server type name, then add SerializationTypeNameAnnotation
            // which tells ODataLib to write the type name in the annotation in the payload.
            if (entityType.ElementTypeName != serverTypeName)
            {
                entry.SetAnnotation(new SerializationTypeNameAnnotation {
                    TypeName = serverTypeName
                });
            }

            // We always need to write the client type name, since this is the type name used by ODataLib
            // to resolve the entity type using EdmModel.FindSchemaElement.
            entry.TypeName = entityType.ElementTypeName;

            // Continue to send the entry's ID in update payloads in Atom for compatibility with V1-V3,
            // but for JSON-Light we do not want the extra information on the wire.
            if (clientFormat.UsingAtom && EntityStates.Modified == entityDescriptor.State)
            {
                // <id>http://host/service/entityset(key)</id>
                entry.Id = entityDescriptor.GetLatestIdentity();
            }

            if (entityDescriptor.IsMediaLinkEntry || entityType.IsMediaLinkEntry)
            {
                // Since we are already enabled EnableWcfDataServicesClientBehavior in the writer settings,
                // setting the MediaResource value will tell ODataLib to write MLE payload, irrespective of
                // what the metadata says.
                entry.MediaResource = new ODataStreamReferenceValue();
            }

            return(entry);
        }
Пример #3
0
        /// <summary>
        /// Writes an entity reference link.
        /// </summary>
        /// <param name="binding">The link descriptor.</param>
        /// <param name="requestMessage">The request message used for writing the payload.</param>
        internal void WriteEntityReferenceLink(LinkDescriptor binding, ODataRequestMessageWrapper requestMessage)
#endif
        {
            using (ODataMessageWriter messageWriter = Serializer.CreateMessageWriter(requestMessage, this.requestInfo, false /*isParameterPayload*/))
            {
                EntityDescriptor targetResource = this.requestInfo.EntityTracker.GetEntityDescriptor(binding.Target);

                Uri targetReferenceLink = targetResource.GetLatestIdentity();

                if (targetReferenceLink == null)
                {
#if DEBUG
                    Debug.Assert(isBatch, "we should be cross-referencing entities only in batch scenarios");
#endif
                    targetReferenceLink = UriUtil.CreateUri("$" + targetResource.ChangeOrder.ToString(CultureInfo.InvariantCulture), UriKind.Relative);
                }

                ODataEntityReferenceLink referenceLink = new ODataEntityReferenceLink();
                referenceLink.Url = targetReferenceLink;
                messageWriter.WriteEntityReferenceLink(referenceLink);
            }
        }
Пример #4
0
        /// <summary>
        /// Creates an ODataEntry for the given EntityDescriptor and fills in its ODataLib metadata.
        /// </summary>
        /// <param name="entityDescriptor">The entity descriptor.</param>
        /// <param name="serverTypeName">Name of the server type.</param>
        /// <param name="entityType">The client-side entity type.</param>
        /// <param name="clientFormat">The current client format.</param>
        /// <returns>An odata entry with its metadata filled in.</returns>
        internal static ODataEntry CreateODataEntry(EntityDescriptor entityDescriptor, string serverTypeName, ClientTypeAnnotation entityType, DataServiceClientFormat clientFormat)
        {
            ODataEntry entry = new ODataEntry();

            // If the client type name is different from the server type name, then add SerializationTypeNameAnnotation
            // which tells ODataLib to write the type name in the annotation in the payload.
            if (entityType.ElementTypeName != serverTypeName)
            {
                entry.SetAnnotation(new SerializationTypeNameAnnotation { TypeName = serverTypeName });
            }

            // We always need to write the client type name, since this is the type name used by ODataLib
            // to resolve the entity type using EdmModel.FindSchemaElement.
            entry.TypeName = entityType.ElementTypeName;

            // Continue to send the entry's ID in update payloads in Atom for compatibility with V1-V3,
            // but for JSON-Light we do not want the extra information on the wire.
            if (clientFormat.UsingAtom && EntityStates.Modified == entityDescriptor.State)
            {
                // <id>http://host/service/entityset(key)</id>
                entry.Id = entityDescriptor.GetLatestIdentity();
            }

            if (entityDescriptor.IsMediaLinkEntry || entityType.IsMediaLinkEntry)
            {
                // Since we are already enabled EnableWcfDataServicesClientBehavior in the writer settings,
                // setting the MediaResource value will tell ODataLib to write MLE payload, irrespective of
                // what the metadata says.
                entry.MediaResource = new ODataStreamReferenceValue();
            }

            return entry;
        }
Пример #5
0
        /// <summary>
        /// Materialize the response payload.
        /// </summary>
        /// <param name="entityDescriptor">entity descriptor whose response is getting materialized.</param>
        /// <param name="responseInfo">information about the response to be materialized.</param>
        /// <param name="etag">etag value, if specified in the response header.</param>
        private void MaterializeResponse(EntityDescriptor entityDescriptor, ResponseInfo responseInfo, string etag)
        {
            using (MaterializeAtom materializer = this.GetMaterializer(entityDescriptor, responseInfo))
            {
                materializer.SetInsertingObject(entityDescriptor.Entity);

                object materializedEntity = null;
                foreach (object x in materializer)
                {
                    Debug.Assert(materializedEntity == null, "entity == null");
                    if (materializedEntity != null)
                    {
                        Error.ThrowInternalError(InternalError.MaterializerReturningMoreThanOneEntity);
                    }

                    materializedEntity = x;
                }

                Debug.Assert(null != entityDescriptor.GetLatestIdentity(), "updated inserted should always gain an identity");
                Debug.Assert(materializedEntity == entityDescriptor.Entity, "x == entityDescriptor.Entity, should have same object generated by response");
                Debug.Assert(EntityStates.Unchanged == entityDescriptor.State, "should have moved out of insert");
                Debug.Assert(this.RequestInfo.EntityTracker.TryGetEntityDescriptor(entityDescriptor.GetLatestIdentity()) != null, "should have identity tracked");

                // If there was no etag specified in the payload, then we need to set the etag from the header
                if (entityDescriptor.GetLatestETag() == null)
                {
                    entityDescriptor.ETag = etag;
                }
            }
        }
Пример #6
0
        /// <summary>
        /// Validates that the link descriptor source and target have identities.
        /// </summary>
        /// <param name="binding">The binding.</param>
        /// <param name="sourceResource">The source resource.</param>
        /// <param name="targetResource">The target resource.</param>
        private static void ValidateLinkDescriptorSourceAndTargetHaveIdentities(LinkDescriptor binding, EntityDescriptor sourceResource, EntityDescriptor targetResource)
        {
            Debug.Assert(!binding.ContentGeneratedForSave, "already saved link");

            // In non-batch scenarios, the source should always have an identity
            if (null == sourceResource.GetLatestIdentity())
            {
                binding.ContentGeneratedForSave = true;
                Debug.Assert(EntityStates.Added == sourceResource.State, "expected added state");
                throw Error.InvalidOperation(Strings.Context_LinkResourceInsertFailure, sourceResource.SaveError);
            }

            if (null != targetResource && null == targetResource.GetLatestIdentity())
            {
                binding.ContentGeneratedForSave = true;
                Debug.Assert(EntityStates.Added == targetResource.State, "expected added state");
                throw Error.InvalidOperation(Strings.Context_LinkResourceInsertFailure, targetResource.SaveError);
            }
        }