/// <summary>
        /// Gets the response for this request.
        /// </summary>
        /// <returns>The response message.</returns>
        /// <remarks>
        /// This method is not part of the IODataRequestMessage interface. It's here to make the usage of these classes easier.
        /// It also handles OData errors by recognizing them and parsing them.
        /// Each implementation of the interfaces is expected to provide its own way to create the instances and or get them somewhere.
        /// </remarks>
        public IODataResponseMessage GetResponse()
        {
            try
            {
                return(new ClientHttpResponseMessage((HttpWebResponse)this.webRequest.GetResponse()));
            }
            catch (WebException webException)
            {
                if (webException.Response != null)
                {
                    // If there is an error response, try to read it.
                    IODataResponseMessage errorResponseMessage = new ClientHttpResponseMessage((HttpWebResponse)webException.Response);
                    using (ODataMessageReader messageReader = new ODataMessageReader(errorResponseMessage))
                    {
                        // The payload kind detection will determine if the payload is an error by looking at the content type (and possibly even the payload).
                        if (messageReader.DetectPayloadKind().Any(payloadKindDetectionResult => payloadKindDetectionResult.PayloadKind == ODataPayloadKind.Error))
                        {
                            // Construct the error message by concatenating all the error messages (including the inner ones).
                            // Makes it easier to debug problems.
                            ODataError error = messageReader.ReadError();

                            // If it is an error throw the ODataErrorException, it's easier to recognize and also read.
                            throw new ODataErrorException(CreateODataErrorExceptionMessage(error), error);
                        }
                    }
                }

                throw;
            }
        }
Esempio n. 2
0
        public void ShouldBeAbleToReadCustomInstanceAnnotationFromErrorInJsonLight()
        {
            const string payload =
                "{" +
                "\"error\":{" +
                "\"code\":\"400\"," +
                "\"message\":\"Resource not found for the segment 'Address'.\"," +
                "\"@instance.annotation\":\"stringValue\"" +
                "}" +
                "}";

            var stream = new MemoryStream(Encoding.UTF8.GetBytes(payload));

            // Read instance annotations
            var readerSettings = new ODataMessageReaderSettings {
                DisableMessageStreamDisposal = false
            };
            IODataResponseMessage messageToRead = new InMemoryMessage {
                StatusCode = 400, Stream = stream
            };

            messageToRead.SetHeader("Content-Type", "application/json;odata.streaming=true");

            using (var messageReader = new ODataMessageReader(messageToRead, readerSettings, Model))
            {
                ODataError error = messageReader.ReadError();
                error.InstanceAnnotations.Should().HaveCount(1).And.Contain(ia => ia.Name == "instance.annotation");
            }
        }
        private static async Task <Exception> ProcessErrorAsync(System.Net.Http.HttpResponseMessage response)
        {
            if (response.Content == null)
            {
                return(null);
            }

            if (response.Content.Headers.ContentType == null)
            {
                return(new System.Net.Http.HttpRequestException(await response.Content.ReadAsStringAsync()));
            }

            using (var stream = await response.Content.ReadAsStreamAsync())
            {
                var headers = response.Content.Headers.ToDictionary(i => i.Key, i => i.Value.FirstOrDefault());

                var httpMessage = new HttpWebResponseMessage(
                    headers,
                    (int)response.StatusCode,
                    () => stream);

                var reader = new ODataMessageReader(httpMessage);

                try
                {
                    var error = reader.ReadError();
                    return(new ODataErrorException(error.Message, null, error));
                }
                catch
                {
                }
            }

            return(null);
        }
        private static Exception ProcessError(Exception outer, DataServiceClientException inner, IDictionary <string, string> headers)
        {
            if (inner == null)
            {
                return(null);
            }

            using (var writer = WriteToStream(inner.Message))
            {
                var httpMessage = new HttpWebResponseMessage(
                    headers,
                    inner.StatusCode,
                    () => writer.BaseStream);

                var reader = new ODataMessageReader(httpMessage);

                try
                {
                    var error = reader.ReadError();
                    return(new ODataErrorException(error.Message, outer, error));
                }
                catch
                {
                }
            }

            return(null);
        }
Esempio n. 5
0
        private void VerifyAtomBeDisabledQueryTest(string uri)
        {
            var message = new HttpWebRequestMessage(new Uri(ServiceBaseUri.AbsoluteUri + uri, UriKind.Absolute));

            message.SetHeader("Accept", MimeTypes.ApplicationAtomXml);

            var responseMessage = message.GetResponse();

            Assert.Equal(415, responseMessage.StatusCode);

            using (var messageReader = new ODataMessageReader(responseMessage))
            {
                var error = messageReader.ReadError();
                Assert.Equal(typeof(Microsoft.OData.ODataError), error.GetType());
                Assert.Equal("UnsupportedMediaType", error.ErrorCode);
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Parses the error details from the stream using OData library.
        /// </summary>
        /// <param name="responseMessage">The IODataResponseMessage to parse.</param>
        /// <returns>The error details.</returns>
        public static StorageExtendedErrorInformation ReadAndParseExtendedError(IODataResponseMessage responseMessage)
        {
            StorageExtendedErrorInformation storageExtendedError = null;

            using (ODataMessageReader reader = new ODataMessageReader(responseMessage))
            {
                try
                {
                    ODataError error = reader.ReadError();
                    if (error != null)
                    {
                        storageExtendedError = new StorageExtendedErrorInformation();
                        storageExtendedError.AdditionalDetails = new Dictionary <string, string>();
                        storageExtendedError.ErrorCode         = error.ErrorCode;
                        storageExtendedError.ErrorMessage      = error.Message;
                        if (error.InnerError != null)
                        {
                            storageExtendedError.AdditionalDetails[Constants.ErrorExceptionMessage] =
                                error.InnerError.Message;
                            storageExtendedError.AdditionalDetails[Constants.ErrorExceptionStackTrace] =
                                error.InnerError.StackTrace;
                        }

#if !(WINDOWS_PHONE && WINDOWS_DESKTOP)
                        if (error.InstanceAnnotations.Count > 0)
                        {
                            foreach (ODataInstanceAnnotation annotation in error.InstanceAnnotations)
                            {
                                storageExtendedError.AdditionalDetails[annotation.Name] =
                                    annotation.Value.GetAnnotation <string>();
                            }
                        }
#endif
                    }
                }
                catch (Exception)
                {
                    // Error cannot be parsed.
                    return(null);
                }
            }

            return(storageExtendedError);
        }
        public void QueryWithAvroError()
        {
            var requestMessage = new HttpWebRequestMessage(new Uri(ServiceBaseUri.AbsoluteUri + "Products(-9)", UriKind.Absolute));

            requestMessage.SetHeader("Accept", "avro/binary");
            var responseMessage = requestMessage.GetResponse();

            Assert.AreEqual(404, responseMessage.StatusCode);
            ODataError error;

            using (var reader = new ODataMessageReader(responseMessage, GetAvroReaderSettings()))
            {
                error = reader.ReadError();
            }

            Assert.IsNotNull(error);
            Assert.AreEqual("NotFound", error.ErrorCode);
            Assert.AreEqual("An server side error occured.", error.Message);
        }
Esempio n. 8
0
        /// <summary>
        /// Reads an ODataError from the stream and returns it for verification.
        /// </summary>
        private ODataError ReadError()
        {
            ODataError readError;
            var        readerSettings = new ODataMessageReaderSettings {
                DisableMessageStreamDisposal = false
            };

            IODataResponseMessage messageToRead = new InMemoryMessage {
                StatusCode = 400, Stream = this.stream
            };

            messageToRead.SetHeader("Content-Type", "application/json;odata.metadata=minimal");

            using (var reader = new ODataMessageReader(messageToRead, readerSettings, this.model))
            {
                readError = reader.ReadError();
            }

            return(readError);
        }
Esempio n. 9
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;
            }
        }
        /// <summary>
        /// Parses the error details from the stream using OData library.
        /// </summary>
        /// <param name="responseMessage">The IODataResponseMessage to parse.</param>
        /// <returns>The error details.</returns>
        public static StorageExtendedErrorInformation ReadAndParseExtendedError(IODataResponseMessage responseMessage)
        {
            StorageExtendedErrorInformation storageExtendedError = null;
            using (ODataMessageReader reader = new ODataMessageReader(responseMessage))
            {
                try
                {
                    ODataError error = reader.ReadError();
                    if (error != null)
                    {
                        storageExtendedError = new StorageExtendedErrorInformation();
                        storageExtendedError.AdditionalDetails = new Dictionary<string, string>();
                        storageExtendedError.ErrorCode = error.ErrorCode;
                        storageExtendedError.ErrorMessage = error.Message;
                        if (error.InnerError != null)
                        {
                            storageExtendedError.AdditionalDetails[Constants.ErrorExceptionMessage] = error.InnerError.Message;
                            storageExtendedError.AdditionalDetails[Constants.ErrorExceptionStackTrace] = error.InnerError.StackTrace;
                        }

#if !(WINDOWS_PHONE && WINDOWS_DESKTOP)
                        if (error.InstanceAnnotations.Count > 0)
                        {
                            foreach (ODataInstanceAnnotation annotation in error.InstanceAnnotations)
                            {
                                storageExtendedError.AdditionalDetails[annotation.Name] = annotation.Value.GetAnnotation<string>();
                            }
                        }
#endif
                    }
                }
                catch (Exception)
                {
                    // Error cannot be parsed. 
                    return null;
                }
            }

            return storageExtendedError;
        }
        /// <summary>
        /// Reads an ODataError from the stream and returns it for verification.
        /// </summary>
        private ODataError ReadError()
        {
            ODataError readError;
            var readerSettings = new ODataMessageReaderSettings { DisableMessageStreamDisposal = false };

            IODataResponseMessage messageToRead = new InMemoryMessage { StatusCode = 400, Stream = this.stream };
            messageToRead.SetHeader("Content-Type", "application/json;odata.metadata=minimal");

            using (var reader = new ODataMessageReader(messageToRead, readerSettings, this.model))
            {
                readError = reader.ReadError();
            }

            return readError;
        }
Esempio n. 12
0
        public static ODataMaterializer CreateMaterializerForMessage(IODataResponseMessage responseMessage, System.Data.Services.Client.ResponseInfo responseInfo, Type materializerType, QueryComponents queryComponents, ProjectionPlan plan, ODataPayloadKind payloadKind)
        {
            ODataMaterializer materializer2;
            bool projectionQuery             = (plan != null) || (queryComponents.Projection != null);
            ODataMessageReader messageReader = CreateODataMessageReader(responseMessage, responseInfo, projectionQuery, ref payloadKind);
            IEdmType           expectedType  = null;

            try
            {
                ODataMaterializer materializer;
                if (materializerType != typeof(object))
                {
                    expectedType = ClientEdmModel.GetModel(responseInfo.MaxProtocolVersion).GetOrCreateEdmType(materializerType);
                }
                if ((payloadKind == ODataPayloadKind.Entry) || (payloadKind == ODataPayloadKind.Feed))
                {
                    if ((expectedType != null) && (expectedType.TypeKind != EdmTypeKind.Entity))
                    {
                        throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.AtomMaterializer_InvalidNonEntityType(materializerType.FullName));
                    }
                    ODataReader reader = CreateODataReader(messageReader, payloadKind, expectedType, responseInfo.MaxProtocolVersion);
                    materializer = new ODataReaderEntityMaterializer(messageReader, reader, responseInfo, queryComponents, materializerType, plan);
                }
                else
                {
                    switch (payloadKind)
                    {
                    case ODataPayloadKind.Property:
                        if ((expectedType != null) && (expectedType.TypeKind == EdmTypeKind.Entity))
                        {
                            throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.AtomMaterializer_InvalidEntityType(materializerType.FullName));
                        }
                        break;

                    case ODataPayloadKind.EntityReferenceLink:
                    case ODataPayloadKind.EntityReferenceLinks:
                        materializer = new ODataLinksMaterializer(messageReader, responseInfo, materializerType, queryComponents.SingleResult);
                        goto Label_013A;

                    case ODataPayloadKind.Value:
                        materializer = new ODataValueMaterializer(messageReader, responseInfo, materializerType, queryComponents.SingleResult);
                        goto Label_013A;

                    case ODataPayloadKind.BinaryValue:
                    case ODataPayloadKind.Collection:
                    case ODataPayloadKind.ServiceDocument:
                    case ODataPayloadKind.MetadataDocument:
                        goto Label_0129;

                    case ODataPayloadKind.Error:
                    {
                        ODataError error = messageReader.ReadError();
                        throw new ODataErrorException(error.Message, error);
                    }

                    default:
                        goto Label_0129;
                    }
                    materializer = new ODataPropertyMaterializer(messageReader, responseInfo, materializerType, queryComponents.SingleResult);
                }
                goto Label_013A;
Label_0129:
                throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.AtomMaterializer_InvalidResponsePayload(responseInfo.DataNamespace));
Label_013A:
                materializer2 = materializer;
            }
            catch (Exception exception)
            {
                if (CommonUtil.IsCatchableExceptionType(exception))
                {
                    messageReader.Dispose();
                }
                throw;
            }
            return(materializer2);
        }
        public void ShouldBeAbleToReadCustomInstanceAnnotationFromErrorInJsonLight()
        {
            const string payload =
            "{" +
                "\"error\":{" +
                    "\"code\":\"400\"," +
                    "\"message\":\"Resource not found for the segment 'Address'.\"," +
                    "\"@instance.annotation\":\"stringValue\"" +
                "}" +
            "}";

            var stream = new MemoryStream(Encoding.UTF8.GetBytes(payload));

            // Read instance annotations
            var readerSettings = new ODataMessageReaderSettings { DisableMessageStreamDisposal = false };
            IODataResponseMessage messageToRead = new InMemoryMessage { StatusCode = 400, Stream = stream };
            messageToRead.SetHeader("Content-Type", "application/json;odata.streaming=true");

            using (var messageReader = new ODataMessageReader(messageToRead, readerSettings, Model))
            {
                ODataError error = messageReader.ReadError();
                error.InstanceAnnotations.Should().HaveCount(1).And.Contain(ia => ia.Name == "instance.annotation");
            }
        }