Esempio n. 1
0
        private void HandleOperationResponseData(HttpWebResponse response, Stream responseStream)
        {
            Version       version;
            Func <Stream> getResponseStream     = null;
            Dictionary <string, string> headers = WebUtil.WrapResponseHeaders(response);
            Descriptor        descriptor        = base.ChangedEntries[base.entryIndex];
            MaterializerEntry entry             = null;
            Exception         exception         = BaseSaveResult.HandleResponse(base.RequestInfo, response.StatusCode, response.Headers["DataServiceVersion"], () => responseStream, false, out version);

            if (((responseStream != null) && (descriptor.DescriptorKind == DescriptorKind.Entity)) && (exception == null))
            {
                EntityDescriptor entityDescriptor = (EntityDescriptor)descriptor;
                if (((entityDescriptor.State == EntityStates.Added) || (entityDescriptor.StreamState == EntityStates.Added)) || ((entityDescriptor.State == EntityStates.Modified) || (entityDescriptor.StreamState == EntityStates.Modified)))
                {
                    try
                    {
                        ResponseInfo responseInfo = base.CreateResponseInfo(entityDescriptor);
                        if (getResponseStream == null)
                        {
                            getResponseStream = () => responseStream;
                        }
                        HttpWebResponseMessage message = new HttpWebResponseMessage(response, getResponseStream);
                        entry = ODataReaderEntityMaterializer.ParseSingleEntityPayload(message, responseInfo, entityDescriptor.Entity.GetType());
                        entityDescriptor.TransientEntityDescriptor = entry.EntityDescriptor;
                    }
                    catch (Exception exception2)
                    {
                        exception = exception2;
                        if (!CommonUtil.IsCatchableExceptionType(exception2))
                        {
                            throw;
                        }
                    }
                }
            }
            this.cachedResponses.Add(new CachedResponse(descriptor, headers, response.StatusCode, version, (entry != null) ? entry.Entry : null, exception));
            if (exception != null)
            {
                descriptor.SaveError = exception;
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Creates an <see cref="ODataMaterializer"/> for a response.
        /// </summary>
        /// <param name="responseMessage">The response message.</param>
        /// <param name="responseInfo">The response context.</param>
        /// <param name="materializerType">The type to materialize.</param>
        /// <param name="queryComponents">The query components for the request.</param>
        /// <param name="plan">The projection plan.</param>
        /// <param name="payloadKind">expected payload kind.</param>
        /// <returns>A materializer specialized for the given response.</returns>
        public static ODataMaterializer CreateMaterializerForMessage(
            IODataResponseMessage responseMessage,
            ResponseInfo responseInfo,
            Type materializerType,
            QueryComponents queryComponents,
            ProjectionPlan plan,
            ODataPayloadKind payloadKind)
        {
            ODataMessageReader messageReader = CreateODataMessageReader(responseMessage, responseInfo, ref payloadKind);

            ODataMaterializer result;
            IEdmType          edmType = null;

            try
            {
                ODataMaterializerContext materializerContext = new ODataMaterializerContext(responseInfo);

                // Since in V1/V2, astoria client allowed Execute<object> and depended on the typeresolver or the wire type name
                // to get the clr type to materialize. Hence if we see the materializer type as object, we should set the edmtype
                // to null, since there is no expected type.
                if (materializerType != typeof(System.Object))
                {
                    edmType = responseInfo.TypeResolver.ResolveExpectedTypeForReading(materializerType);
                }

                if (payloadKind == ODataPayloadKind.Property && edmType != null)
                {
                    if (edmType.TypeKind.IsStructured())
                    {
                        payloadKind = ODataPayloadKind.Resource;
                    }
                    else if (edmType.TypeKind == EdmTypeKind.Collection && (edmType as IEdmCollectionType).ElementType.IsStructured())
                    {
                        payloadKind = ODataPayloadKind.ResourceSet;
                    }
                }

                if (payloadKind == ODataPayloadKind.Resource || payloadKind == ODataPayloadKind.ResourceSet)
                {
                    // In V1/V2, we allowed System.Object type to be allowed to pass to ExecuteQuery.
                    // Hence we need to explicitly check for System.Object to allow this
                    if (edmType != null && !edmType.TypeKind.IsStructured())
                    {
                        throw DSClient.Error.InvalidOperation(DSClient.Strings.AtomMaterializer_InvalidNonEntityType(materializerType.FullName));
                    }

                    ODataReaderWrapper       reader = ODataReaderWrapper.Create(messageReader, payloadKind, edmType, responseInfo.ResponsePipeline);
                    EntityTrackingAdapter    entityTrackingAdapter    = new EntityTrackingAdapter(responseInfo.EntityTracker, responseInfo.MergeOption, responseInfo.Model, responseInfo.Context);
                    LoadPropertyResponseInfo loadPropertyResponseInfo = responseInfo as LoadPropertyResponseInfo;

                    if (loadPropertyResponseInfo != null)
                    {
                        result = new ODataLoadNavigationPropertyMaterializer(
                            messageReader,
                            reader,
                            materializerContext,
                            entityTrackingAdapter,
                            queryComponents,
                            materializerType,
                            plan,
                            loadPropertyResponseInfo);
                    }
                    else
                    {
                        result = new ODataReaderEntityMaterializer(
                            messageReader,
                            reader,
                            materializerContext,
                            entityTrackingAdapter,
                            queryComponents,
                            materializerType,
                            plan);
                    }
                }
                else
                {
                    switch (payloadKind)
                    {
                    case ODataPayloadKind.Value:
                        result = new ODataValueMaterializer(messageReader, materializerContext, materializerType, queryComponents.SingleResult);
                        break;

                    case ODataPayloadKind.Collection:
                        result = new ODataCollectionMaterializer(messageReader, materializerContext, materializerType, queryComponents.SingleResult);
                        break;

                    case ODataPayloadKind.Property:
                    case ODataPayloadKind.IndividualProperty:
                        // Top level properties cannot be of entity type.
                        if (edmType != null && (edmType.TypeKind == EdmTypeKind.Entity || edmType.TypeKind == EdmTypeKind.Complex))
                        {
                            throw DSClient.Error.InvalidOperation(DSClient.Strings.AtomMaterializer_InvalidEntityType(materializerType.FullName));
                        }

                        result = new ODataPropertyMaterializer(messageReader, materializerContext, materializerType, queryComponents.SingleResult);
                        break;

                    case ODataPayloadKind.EntityReferenceLinks:
                    case ODataPayloadKind.EntityReferenceLink:
                        result = new ODataLinksMaterializer(messageReader, materializerContext, materializerType, queryComponents.SingleResult);
                        break;

                    case ODataPayloadKind.Error:
                        var odataError = messageReader.ReadError();
                        throw new ODataErrorException(odataError.Message, odataError);

                    default:
                        throw DSClient.Error.InvalidOperation(DSClient.Strings.AtomMaterializer_InvalidResponsePayload(XmlConstants.DataWebNamespace));
                    }
                }

                return(result);
            }
            catch (Exception ex)
            {
                if (CommonUtil.IsCatchableExceptionType(ex))
                {
                    // Dispose the message reader in all error scenarios.
                    messageReader.Dispose();
                }

                throw;
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Handle the response payload.
        /// </summary>
        /// <param name="responseMsg">httpwebresponse instance.</param>
        /// <param name="responseStream">stream containing the response payload.</param>
        private void HandleOperationResponseData(IODataResponseMessage responseMsg, Stream responseStream)
        {
            Debug.Assert(this.entryIndex >= 0 && this.entryIndex < this.ChangedEntries.Count, string.Format(System.Globalization.CultureInfo.InvariantCulture, "this.entryIndex = '{0}', this.ChangedEntries.Count() = '{1}'", this.entryIndex, this.ChangedEntries.Count));

            // Parse the response
            Descriptor        current = this.ChangedEntries[this.entryIndex];
            MaterializerEntry entry   = default(MaterializerEntry);
            Version           responseVersion;
            Exception         exception = BaseSaveResult.HandleResponse(this.RequestInfo, (HttpStatusCode)responseMsg.StatusCode, responseMsg.GetHeader(XmlConstants.HttpODataVersion), () => { return(responseStream); }, false /*throwOnFailure*/, out responseVersion);

            var headers = new HeaderCollection(responseMsg);

            if (responseStream != null && current.DescriptorKind == DescriptorKind.Entity && exception == null)
            {
                // Only process the response if the current resource is an entity and it's an insert or update scenario
                EntityDescriptor entityDescriptor = (EntityDescriptor)current;

                // We were ignoring the payload for non-insert and non-update scenarios. We need to keep doing that.
                if (entityDescriptor.State == EntityStates.Added || entityDescriptor.StreamState == EntityStates.Added ||
                    entityDescriptor.State == EntityStates.Modified || entityDescriptor.StreamState == EntityStates.Modified)
                {
                    try
                    {
                        ResponseInfo responseInfo           = this.CreateResponseInfo(entityDescriptor);
                        var          responseMessageWrapper = new HttpWebResponseMessage(
                            headers,
                            responseMsg.StatusCode,
                            () => responseStream);

                        entry = ODataReaderEntityMaterializer.ParseSingleEntityPayload(responseMessageWrapper, responseInfo, entityDescriptor.Entity.GetType());
                        entityDescriptor.TransientEntityDescriptor = entry.EntityDescriptor;
                    }
                    catch (Exception ex)
                    {
                        exception = ex;

                        if (!CommonUtil.IsCatchableExceptionType(ex))
                        {
                            throw;
                        }
                    }
                }
            }

            this.cachedResponses.Add(new CachedResponse(
                                         current,
                                         headers,
                                         (HttpStatusCode)responseMsg.StatusCode,
                                         responseVersion,
                                         entry,
                                         exception));

            if (exception != null)
            {
                current.SaveError = exception;

                // DEVNOTE(pqian):
                // There are two possible scenario here:
                // 1. We are in the sync code path, and there's an in stream error on the server side, or there are bad xml thrown
                // 2. We are in the async code path, there's a error thrown on the server side (any error)
                // Ideally, we need to check whether we want to continue to the next changeset. (Call this.CheckContinueOnError)
                // However, in V1/V2, we did not do this. Thus we will always continue on error on these scenarios
            }
        }