/// <summary> /// Create context URL from ODataPayloadKind and ODataContextUrlInfo. /// should make the context uri correct for null primitive / null enum value / normal enum value /// ODataEnumValue is allowed to have null or arbitrary TypeName, but the output ContextUri must have correct type name. /// </summary> /// <param name="payloadKind">The ODataPayloadKind for the context URI.</param> /// <param name="contextInfo">The ODataContextUrlInfo to be used.</param> /// <returns>The generated context url.</returns> internal Uri BuildContextUri(ODataPayloadKind payloadKind, ODataContextUrlInfo contextInfo = null) { if (this.baseContextUrl == null) { return null; } Action<ODataContextUrlInfo> verifyAction; if (ValidationDictionary.TryGetValue(payloadKind, out verifyAction)) { if (verifyAction != null && throwIfMissingInfo) { Debug.Assert(contextInfo != null, "contextInfo != null"); verifyAction(contextInfo); } } else { throw new ODataException(Strings.ODataContextUriBuilder_UnsupportedPayloadKind(payloadKind.ToString())); } switch (payloadKind) { case ODataPayloadKind.ServiceDocument: return this.baseContextUrl; case ODataPayloadKind.EntityReferenceLink: return new Uri(this.baseContextUrl, ODataConstants.SingleEntityReferencesContextUrlSegment); case ODataPayloadKind.EntityReferenceLinks: return new Uri(this.baseContextUrl, ODataConstants.CollectionOfEntityReferencesContextUrlSegment); } return CreateFromContextUrlInfo(contextInfo); }
/// <summary> /// Determines the response format based on the results of content negotiation. /// </summary> /// <param name="payloadKind">The payload kind of the response.</param> /// <param name="acceptableMediaTypes"> /// The acceptable media types used to determine the content type of the message. /// This is a comma separated list of content types as specified in RFC 2616, Section 14.1 /// </param> /// <param name="acceptableCharSets"> /// The acceptable charsets to use to the determine the encoding of the message. /// This is a comma separated list of charsets as specified in RFC 2616, Section 14.2 /// </param> /// <returns>The format the response should use. </returns> internal ODataFormatWithParameters DetermineResponseFormat(ODataPayloadKind payloadKind, string acceptableMediaTypes, string acceptableCharSets) { Debug.Assert(payloadKind != ODataPayloadKind.Unsupported, "kind != ODataPayloadKind.Unsupported"); ContentNegotiationResponseMessage responseMessage = new ContentNegotiationResponseMessage(); ODataMessageWriterSettings settings = new ODataMessageWriterSettings { Version = this.responseVersion }; settings.EnableAtomSupport(); settings.SetContentType(acceptableMediaTypes, acceptableCharSets); try { using (ODataMessageWriter writer = new ODataMessageWriter(responseMessage, settings)) { ODataFormat format = ODataUtils.SetHeadersForPayload(writer, payloadKind); return new ODataFormatWithParameters(format, responseMessage.ContentType); } } catch (ODataContentTypeException exception) { if (this.throwIfNoMatch) { throw new DataServiceException(415, null, Microsoft.OData.Service.Strings.DataServiceException_UnsupportedMediaType, null, exception); } return null; } }
internal static bool IsPayloadKindSupported(ODataPayloadKind payloadKind, bool inRequest) { switch (payloadKind) { case ODataPayloadKind.Feed: case ODataPayloadKind.EntityReferenceLinks: case ODataPayloadKind.Collection: case ODataPayloadKind.ServiceDocument: case ODataPayloadKind.MetadataDocument: case ODataPayloadKind.Error: return !inRequest; case ODataPayloadKind.Entry: case ODataPayloadKind.Property: case ODataPayloadKind.EntityReferenceLink: case ODataPayloadKind.Value: case ODataPayloadKind.BinaryValue: case ODataPayloadKind.Batch: return true; case ODataPayloadKind.Parameter: return inRequest; } throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataUtilsInternal_IsPayloadKindSupported_UnreachableCodePath)); }
/// <summary> /// Creates a context URI parser and parses the context URI read from the payload. /// </summary> /// <param name="model">The model to use when resolving the target of the URI.</param> /// <param name="contextUriFromPayload">The string value of the odata.metadata annotation read from the payload.</param> /// <param name="payloadKind">The payload kind we expect the context URI to conform to.</param> /// <param name="readerBehavior">Reader behavior if the caller is a reader, null if no reader behavior is available.</param> /// <param name="needParseFragment">Whether the fragment after $metadata should be parsed, if set to false, only MetadataDocumentUri is parsed.</param> /// <returns>The result from parsing the context URI.</returns> internal static ODataJsonLightContextUriParseResult Parse( IEdmModel model, string contextUriFromPayload, ODataPayloadKind payloadKind, ODataReaderBehavior readerBehavior, bool needParseFragment) { if (contextUriFromPayload == null) { throw new ODataException(ODataErrorStrings.ODataJsonLightContextUriParser_NullMetadataDocumentUri); } // Create an absolute URI from the payload string // TODO: Support relative context uri and resolving other relative uris Uri contextUri; if (!Uri.TryCreate(contextUriFromPayload, UriKind.Absolute, out contextUri)) { throw new ODataException(ODataErrorStrings.ODataJsonLightContextUriParser_TopLevelContextUrlShouldBeAbsolute(contextUriFromPayload)); } ODataJsonLightContextUriParser parser = new ODataJsonLightContextUriParser(model, contextUri); parser.TokenizeContextUri(); if (needParseFragment) { parser.ParseContextUri(payloadKind, readerBehavior); } return parser.parseResult; }
internal ODataRawInputContext( ODataFormat format, Stream messageStream, Encoding encoding, ODataMessageReaderSettings messageReaderSettings, bool readingResponse, bool synchronous, IEdmModel model, IODataUrlResolver urlResolver, ODataPayloadKind readerPayloadKind) : base(format, messageReaderSettings, readingResponse, synchronous, model, urlResolver) { Debug.Assert(messageStream != null, "stream != null"); Debug.Assert(readerPayloadKind != ODataPayloadKind.Unsupported, "readerPayloadKind != ODataPayloadKind.Unsupported"); ExceptionUtils.CheckArgumentNotNull(format, "format"); ExceptionUtils.CheckArgumentNotNull(messageReaderSettings, "messageReaderSettings"); try { this.stream = messageStream; this.encoding = encoding; this.readerPayloadKind = readerPayloadKind; } catch (Exception e) { // Dispose the message stream if we failed to create the input context. if (ExceptionUtils.IsCatchableExceptionType(e) && messageStream != null) { messageStream.Dispose(); } throw; } }
public static void Validate(ODataPayloadKind payloadKind, string parameterName) { if (!IsDefined(payloadKind)) { throw Error.InvalidEnumArgument(parameterName, (int)payloadKind, typeof(ODataPayloadKind)); } }
public override IEnumerable<ODataMediaTypeFormat> GetMediaTypeFormats(ODataPayloadKind payloadKind) { if (payloadKind == ODataPayloadKind.Property) { return mediaTypeFormats.Concat(base.GetMediaTypeFormats(payloadKind)); } return base.GetMediaTypeFormats(payloadKind); }
internal ResponseBodyWriter(bool hasMoved, IDataService service, IEnumerator queryResults, RequestDescription requestDescription, IODataResponseMessage responseMessage, ODataPayloadKind payloadKind) { this.hasMoved = hasMoved; this.service = service; this.queryResults = queryResults; this.requestDescription = requestDescription; this.responseMessage = responseMessage; this.payloadKind = payloadKind; this.encoding = HttpProcessUtility.EncodingFromAcceptCharset(this.service.OperationContext.Host.RequestAcceptCharSet); if ((((payloadKind == ODataPayloadKind.Entry) || (payloadKind == ODataPayloadKind.Feed)) || ((payloadKind == ODataPayloadKind.Property) || (payloadKind == ODataPayloadKind.Collection))) || (((payloadKind == ODataPayloadKind.EntityReferenceLink) || (payloadKind == ODataPayloadKind.EntityReferenceLinks)) || (((payloadKind == ODataPayloadKind.Error) || (payloadKind == ODataPayloadKind.ServiceDocument)) || (payloadKind == ODataPayloadKind.Parameter)))) { DataServiceHostWrapper host = service.OperationContext.Host; if (WebUtil.GetEffectiveMaxResponseVersion(service.Configuration.DataServiceBehavior.MaxProtocolVersion, host.RequestMaxVersion) > RequestDescription.Version2Dot0) { bool isEntityOrFeed = (payloadKind == ODataPayloadKind.Entry) || (payloadKind == ODataPayloadKind.Feed); if (WebUtil.ResponseMediaTypeWouldBeJsonLight(host.RequestAccept, isEntityOrFeed)) { requestDescription.VerifyAndRaiseResponseVersion(RequestDescription.Version3Dot0, service); host.ResponseVersion = RequestDescription.Version3Dot0.ToString() + ";"; } } } if (this.requestDescription.TargetKind == RequestTargetKind.MediaResource) { this.mediaResourceStream = service.StreamProvider.GetReadStream(this.queryResults.Current, RequestDescription.GetStreamProperty(this.requestDescription), this.service.OperationContext); } else if (payloadKind != ODataPayloadKind.BinaryValue) { string requestAcceptCharSet = this.service.OperationContext.Host.RequestAcceptCharSet; if (string.IsNullOrEmpty(requestAcceptCharSet) || (requestAcceptCharSet == "*")) { requestAcceptCharSet = "UTF-8"; } if ((payloadKind == ODataPayloadKind.Value) && !string.IsNullOrEmpty(this.requestDescription.MimeType)) { this.messageWriter = CreateMessageWriter(this.AbsoluteServiceUri, this.service, this.requestDescription.ActualResponseVersion, responseMessage, ODataFormat.RawValue); } else { this.messageWriter = CreateMessageWriter(this.AbsoluteServiceUri, this.service, this.requestDescription.ActualResponseVersion, responseMessage, this.service.OperationContext.Host.RequestAccept, requestAcceptCharSet); } try { this.contentFormat = ODataUtils.SetHeadersForPayload(this.messageWriter, payloadKind); if ((payloadKind == ODataPayloadKind.Value) && !string.IsNullOrEmpty(this.requestDescription.MimeType)) { responseMessage.SetHeader("Content-Type", this.requestDescription.MimeType); } } catch (ODataContentTypeException exception) { throw new DataServiceException(0x19f, null, System.Data.Services.Strings.DataServiceException_UnsupportedMediaType, null, exception); } string headerValue = this.requestDescription.ResponseVersion.ToString() + ";"; responseMessage.SetHeader("DataServiceVersion", headerValue); } }
/// <summary> /// Initializes a new instance of the <see cref="ODataEntryDeserializer"/> class. /// </summary> /// <param name="edmType">The EDM type.</param> /// <param name="payloadKind">The kind of OData payload that this deserializer reads.</param> protected ODataEntryDeserializer(IEdmTypeReference edmType, ODataPayloadKind payloadKind) : base(payloadKind) { if (edmType == null) { throw Error.ArgumentNull("edmType"); } EdmType = edmType; }
/// <summary> /// Initializes a new instance of the <see cref="ODataEdmTypeSerializer"/> class. /// </summary> /// <param name="payloadKind">The kind of OData payload that this serializer generates.</param> /// <param name="serializerProvider">The <see cref="ODataSerializerProvider"/> to use to write inner objects.</param> protected ODataEdmTypeSerializer(ODataPayloadKind payloadKind, ODataSerializerProvider serializerProvider) : this(payloadKind) { if (serializerProvider == null) { throw Error.ArgumentNull("serializerProvider"); } SerializerProvider = serializerProvider; }
/// <summary> /// Initializes a new instance of the <see cref="ODataEdmTypeDeserializer"/> class. /// </summary> /// <param name="payloadKind">The kind of OData payload this deserializer handles.</param> /// <param name="deserializerProvider">The <see cref="ODataDeserializerProvider"/>.</param> protected ODataEdmTypeDeserializer(ODataPayloadKind payloadKind, ODataDeserializerProvider deserializerProvider) : this(payloadKind) { if (deserializerProvider == null) { throw Error.ArgumentNull("deserializerProvider"); } DeserializerProvider = deserializerProvider; }
protected ODataEntrySerializer(IEdmTypeReference edmType, ODataPayloadKind odataPayloadKind, ODataSerializerProvider serializerProvider) : this(edmType, odataPayloadKind) { if (serializerProvider == null) { throw Error.ArgumentNull("serializerProvider"); } SerializerProvider = serializerProvider; }
internal MaterializeAtom(ResponseInfo responseInfo, QueryComponents queryComponents, ProjectionPlan plan, IODataResponseMessage responseMessage, ODataPayloadKind payloadKind) { Type type; this.responseInfo = responseInfo; this.elementType = queryComponents.LastSegmentType; this.MergeOptionValue = responseInfo.MergeOption; this.expectingPrimitiveValue = PrimitiveType.IsKnownNullableType(this.elementType); Type materializerType = GetTypeForMaterializer(this.expectingPrimitiveValue, this.elementType, responseInfo.MaxProtocolVersion, out type); this.materializer = ODataMaterializer.CreateMaterializerForMessage(responseMessage, responseInfo, materializerType, queryComponents, plan, payloadKind); }
/// <summary>Sets the content-type and OData-Version headers on the message used by the message writer.</summary> /// <returns>The content-type and OData-Version headers on the message used by the message writer.</returns> /// <param name="messageWriter">The message writer to set the headers for.</param> /// <param name="payloadKind">The kind of payload to be written with the message writer.</param> /// <remarks> /// This method can be called if it is important to set all the message headers before calling any of the /// write methods on the <paramref name="messageWriter"/>. /// If it is sufficient to set the headers when the write methods on the <paramref name="messageWriter"/> /// are called, you don't have to call this method and setting the headers will happen automatically. /// </remarks> public static ODataFormat SetHeadersForPayload(ODataMessageWriter messageWriter, ODataPayloadKind payloadKind) { ExceptionUtils.CheckArgumentNotNull(messageWriter, "messageWriter"); if (payloadKind == ODataPayloadKind.Unsupported) { throw new ArgumentException(Strings.ODataMessageWriter_CannotSetHeadersWithInvalidPayloadKind(payloadKind), "payloadKind"); } return messageWriter.SetHeaders(payloadKind); }
/// <summary> /// Verifies that the result of the test (the message reader) is what the test expected. /// </summary> /// <param name="messageReader">The message reader which is the result of the test. This method should use it to read the results /// of the parsing and verify those.</param> /// <param name="payloadKind">The payload kind specified in the test descriptor.</param> /// <param name="testConfiguration">The test configuration to use.</param> public override void VerifyResult( ODataMessageReaderTestWrapper messageReader, ODataPayloadKind payloadKind, ReaderTestConfiguration testConfiguration) { // First compare the payload kind detection results. IEnumerable<ODataPayloadKindDetectionResult> actualDetectionResults = messageReader.DetectPayloadKind(); this.VerifyPayloadKindDetectionResult(actualDetectionResults); // Then try to read the message as the detected kind if requested if (this.ReadDetectedPayloads) { bool firstResult = true; foreach (PayloadKindDetectionResult result in this.ExpectedDetectionResults) { if (firstResult) { // For the first result use the existing message reader firstResult = false; } else { // For all subsequent results we need to reset the test stream and create a new message reader // over it. this.TestMessage.Reset(); messageReader = TestReaderUtils.CreateMessageReader(this.TestMessage, result.Model, testConfiguration); // Detect the payload kinds again and make sure we can also read the subsequent payload kinds // immediately after detection. actualDetectionResults = messageReader.DetectPayloadKind(); this.VerifyPayloadKindDetectionResult(actualDetectionResults); } TestExceptionUtils.ExpectedException( this.settings.Assert, () => { using (messageReader) { this.settings.MessageToObjectModelReader.ReadMessage( messageReader, result.PayloadKind, result.Model, new PayloadReaderTestDescriptor.ReaderMetadata(result.ExpectedType), /*expectedBatchPayload*/ null, testConfiguration); } }, result.ExpectedException, this.settings.ExceptionVerifier); } } }
public override IEnumerable<ODataMediaTypeFormat> GetMediaTypeFormats(ODataPayloadKind payloadKind) { if (payloadKind == ODataPayloadKind.Property) { return VCardMediaTypeResolver.Instance.GetMediaTypeFormats(payloadKind); } else if (payloadKind == ODataPayloadKind.Entry || payloadKind == ODataPayloadKind.Feed) { return CsvMediaTypeResolver.Instance.GetMediaTypeFormats(payloadKind); } return base.GetMediaTypeFormats(payloadKind); }
/// <summary> /// Verifies that the result of the test is what the test expected. /// </summary> /// <param name="stream">The stream after writing the message content. This method should use it /// to read the message content and verify it.</param> /// <param name="payloadKind">The payload kind specified in the test descriptor.</param> /// <param name="testConfiguration">The test configuration to use.</param> public override void VerifyResult( TestMessage message, ODataPayloadKind payloadKind, WriterTestConfiguration testConfiguration, BaselineLogger logger) { // Get observed payload #if !SILVERLIGHT var observed = TestWriterUtils.ReadToString(message); if (logger != null) logger.LogPayload(TestWriterUtils.BaseLineFixup(observed)); #endif // TODO: Handle SILVERLIGHT }
/// <summary> /// Verifies the result of the write-read. /// </summary> /// <param name="message">The test message is not used but is required to keep the method signature the same.</param> /// <param name="payloadKind">The payload kind is not used but is required to keep the method signature the same.</param> /// <param name="testConfiguration">The test configuration is used for some fixups.</param> public override void VerifyResult(TestMessage message, ODataPayloadKind payloadKind, WriterTestConfiguration testConfiguration, BaselineLogger logger=null) { //TODO: Use Logger to verify result, right now this change is only to unblock writer testcase checkin Debug.Assert(ObservedElement != null, "ObservedElement not provided"); // Fixup the expected and get the content type ODataPayloadElement expected = this.ExpectedPayload.DeepCopy(); ODataPayloadElement observed = this.ObservedElement.DeepCopy(); observed.Accept(new RemoveTypeNameAnnotationFromComplexInCollection()); expected.Accept(new ReorderProperties()); expected.Accept(new RemoveComplexWithNoProperties()); // Compare this.settings.PayloadElementComparer.Compare(expected, observed); }
/// <summary> /// Verifies that the result of the test (the message reader) is what the test expected. /// </summary> /// <param name="messageReader">The message reader which is the result of the test. This method should use it to read the results /// of the parsing and verify those.</param> /// <param name="payloadKind">The payload kind specified in the test descriptor.</param> /// <param name="testConfiguration">The test configuration to use.</param> public override void VerifyResult( ODataMessageReaderTestWrapper messageReader, ODataPayloadKind payloadKind, ReaderTestConfiguration testConfiguration) { this.settings.Assert.IsTrue(payloadKind == ODataPayloadKind.MetadataDocument, "Only metadata payload kind is supported."); object metadata = this.settings.MessageToObjectModelReader.ReadMessage( messageReader, payloadKind, /*payloadModel*/ null, PayloadReaderTestDescriptor.ReaderMetadata.None, /*expectedBatchPayload*/ null, testConfiguration); IEdmModel actualModel = metadata as IEdmModel; this.settings.Assert.IsTrue(metadata != null && actualModel != null, "Expected a non-null model to be read."); }
public static bool IsDefined(ODataPayloadKind payloadKind) { return payloadKind == ODataPayloadKind.Batch || payloadKind == ODataPayloadKind.BinaryValue || payloadKind == ODataPayloadKind.Collection || payloadKind == ODataPayloadKind.EntityReferenceLink || payloadKind == ODataPayloadKind.EntityReferenceLinks || payloadKind == ODataPayloadKind.Entry || payloadKind == ODataPayloadKind.Error || payloadKind == ODataPayloadKind.Feed || payloadKind == ODataPayloadKind.MetadataDocument || payloadKind == ODataPayloadKind.Parameter || payloadKind == ODataPayloadKind.Property || payloadKind == ODataPayloadKind.ServiceDocument || payloadKind == ODataPayloadKind.Value || payloadKind == ODataPayloadKind.Unsupported; }
/// <summary> /// Verifies that the result of the test is what the test expected. /// </summary> /// <param name="stream">The stream after writing the message content. This method should use it /// to read the message content and verify it.</param> /// <param name="payloadKind">The payload kind specified in the test descriptor.</param> /// <param name="testConfiguration">The test configuration to use.</param> public override void VerifyResult( TestMessage message, ODataPayloadKind payloadKind, WriterTestConfiguration testConfiguration, BaselineLogger logger) { this.settings.Assert.IsTrue(payloadKind == ODataPayloadKind.MetadataDocument, "Only metadata payload kind is supported."); // read the message content using the Taupo infrastructure ExceptionUtilities.CheckArgumentNotNull(message.TestStream, "stream != null"); #if !SILVERLIGHT var observed = TestWriterUtils.ReadToString(message); if (logger != null) logger.LogPayload(TestWriterUtils.BaseLineFixup(observed)); #endif // TODO: Handle SILVERLIGHT }
private ODataRawInputContext(ODataFormat format, System.IO.Stream messageStream, Encoding encoding, ODataMessageReaderSettings messageReaderSettings, ODataVersion version, bool readingResponse, bool synchronous, IEdmModel model, IODataUrlResolver urlResolver, ODataPayloadKind readerPayloadKind) : base(format, messageReaderSettings, version, readingResponse, synchronous, model, urlResolver) { ExceptionUtils.CheckArgumentNotNull<ODataFormat>(format, "format"); ExceptionUtils.CheckArgumentNotNull<ODataMessageReaderSettings>(messageReaderSettings, "messageReaderSettings"); try { this.stream = messageStream; this.encoding = encoding; this.readerPayloadKind = readerPayloadKind; } catch (Exception exception) { if (ExceptionUtils.IsCatchableExceptionType(exception) && (messageStream != null)) { messageStream.Dispose(); } throw; } }
/// <summary> /// Verifies that the result of the test (the message reader) is what the test expected. /// </summary> /// <param name="messageReader">The message reader which is the result of the test. This method should use it to read the results /// of the parsing and verify those.</param> /// <param name="payloadKind">The payload kind specified in the test descriptor.</param> /// <param name="testConfiguration">The test configuration to use.</param> public override void VerifyResult( ODataMessageReaderTestWrapper messageReader, ODataPayloadKind payloadKind, ReaderTestConfiguration testConfiguration) { object odataObject = this.settings.MessageToObjectModelReader.ReadMessage( messageReader, ODataPayloadKind.Batch, this.PayloadModel, PayloadReaderTestDescriptor.ReaderMetadata.None, this.ExpectedBatchPayload, testConfiguration); // only compare the payloads if the expected payload is not 'null'; null indicates to skip the comparison if (this.ExpectedBatchPayload != null) { ODataPayloadElement actualPayloadElement = this.settings.ObjectModelToPayloadElementConverter.Convert(odataObject, !testConfiguration.IsRequest); this.settings.BatchComparer.CompareBatchPayload(this.ExpectedBatchPayload, actualPayloadElement); } }
/// <summary> /// Write payload kind to message. /// </summary> /// <param name="messageWriter">Message writer to write payload to.</param> /// <param name="payloadKind">The kind of payload we are writing.</param> /// <param name="payload">The payload to write.</param> /// <param name="functionImport">Function import whose parameters are to be written when the payload kind is Parameters.</param> /// <returns>The object read after writing.</returns> public ODataItem WriteMessage(ODataMessageWriterTestWrapper messageWriter, ODataMessageReaderTestWrapper messageReader, ODataPayloadKind payloadKind, object payload, IEdmOperationImport functionImport = null) { ExceptionUtilities.CheckArgumentNotNull(messageWriter, "messageWriter"); ExceptionUtilities.CheckArgumentNotNull(messageReader, "messageReader"); switch (payloadKind) { case ODataPayloadKind.Feed: this.WriteTopLevelFeed(messageWriter, messageReader, (ODataFeed)payload); break; case ODataPayloadKind.Entry: this.WriteTopLevelEntry(messageWriter, messageReader, (ODataEntry)payload); break; default: ExceptionUtilities.Assert(false, "The payload kind '{0}' is not yet supported by ObjectModelWriteReadStreamer.", payloadKind); break; } return readItems.SingleOrDefault(); }
public void StreamMessage(ODataMessageReaderTestWrapper reader, ODataMessageWriterTestWrapper writer, ODataPayloadKind payloadKind, WriterTestConfiguration config) { ExceptionUtilities.CheckArgumentNotNull(reader, "reader is required"); ExceptionUtilities.CheckArgumentNotNull(writer, "writer is required"); ExceptionUtilities.CheckArgumentNotNull(payloadKind, "payloadKind is required"); ExceptionUtilities.CheckArgumentNotNull(config, "config is required"); this.testConfiguration = config; switch(payloadKind) { case ODataPayloadKind.Entry: this.StartRead(reader.CreateODataEntryReader(), writer.CreateODataEntryWriter()); break; case ODataPayloadKind.Feed: this.StartRead(reader.CreateODataFeedReader(), writer.CreateODataFeedWriter()); break; default: throw new NotSupportedException("ObjectModelReadWriteStreamer currently supports only feed and entry"); }; }
public override IEnumerable<ODataMediaTypeFormat> GetMediaTypeFormats(ODataPayloadKind payloadKind) { var payloadFormats = base.GetMediaTypeFormats(payloadKind); if (payloadKind == ODataPayloadKind.Property) { payloadFormats = payloadFormats.Concat(vcardFormats); } #if ENABLE_AVRO if (payloadKind == ODataPayloadKind.Feed || payloadKind == ODataPayloadKind.Entry || payloadKind == ODataPayloadKind.Property || payloadKind == ODataPayloadKind.Collection || payloadKind == ODataPayloadKind.Parameter || payloadKind == ODataPayloadKind.Error) { payloadFormats = payloadFormats.Concat(avroFormats); } #endif return payloadFormats; }
private void MaterializeTest(HttpStatusCode statusCode, ODataPayloadKind payloadKind) { var uri = new Uri("http://any"); var context = new DataServiceContext(); var requestInfo = new RequestInfo(context); var responseInfo = new ResponseInfo(requestInfo, MergeOption.OverwriteChanges); var queryComponents = new QueryComponents(uri, new Version(4, 0), typeof(Product), null, null); var responseMessage = new HttpWebResponseMessage( new HeaderCollection(), (int)statusCode, () => new MemoryStream()); var materialize = DataServiceRequest.Materialize( responseInfo, queryComponents, null, "application/json", responseMessage, payloadKind); Assert.IsNull(materialize.Context); Assert.IsNull(materialize.Current); var enumerable = materialize.Cast<object>(); Assert.AreEqual(0, enumerable.Count()); }
private void CheckForNavigationLinkWithContent(ODataPayloadKind contentPayloadKind) { Scope currentScope = this.CurrentScope; if ((currentScope.State == WriterState.NavigationLink) || (currentScope.State == WriterState.NavigationLinkWithContent)) { Action action = null; ODataNavigationLink currentNavigationLink = (ODataNavigationLink) currentScope.Item; IEdmType navigationPropertyType = null; this.InterceptException(delegate { navigationPropertyType = WriterValidationUtils.ValidateNavigationLink(currentNavigationLink, this.ParentEntryEntityType, new ODataPayloadKind?(contentPayloadKind)); ((NavigationLinkScope) this.CurrentScope).NavigationPropertyType = navigationPropertyType; }); if (currentScope.State != WriterState.NavigationLinkWithContent) { this.PromoteNavigationLinkScope(); if (!this.SkipWriting) { if (action == null) { action = delegate { this.DuplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(currentNavigationLink, contentPayloadKind != ODataPayloadKind.EntityReferenceLink, new bool?(contentPayloadKind == ODataPayloadKind.Feed)); this.StartNavigationLinkWithContent(currentNavigationLink); }; } this.InterceptException(action); } } else if (this.outputContext.WritingResponse || (currentNavigationLink.IsCollection != true)) { this.ThrowODataException(Microsoft.Data.OData.Strings.ODataWriterCore_MultipleItemsInNavigationLinkContent, currentNavigationLink); } } else if (contentPayloadKind == ODataPayloadKind.EntityReferenceLink) { this.ThrowODataException(Microsoft.Data.OData.Strings.ODataWriterCore_EntityReferenceLinkWithoutNavigationLink, null); } }
/// <summary> /// Creates an exception which reports that the specified payload kind if not support by this format. /// </summary> /// <param name="payloadKind">The payload kind which is not supported.</param> /// <returns>An exception to throw.</returns> private ODataException CreatePayloadKindNotSupportedException(ODataPayloadKind payloadKind) { return(new ODataException(Strings.ODataInputContext_UnsupportedPayloadKindForFormat(this.format.ToString(), payloadKind.ToString()))); }
/// <summary> /// Set the default content type header for a message of the given payload kind. /// </summary> /// <param name="testMessage">The test message to set the Content-Type header on.</param> /// <param name="format">The format of the message.</param> /// <param name="payloadKind">The payload kind for which to determine and set the content type.</param> public static void SetContentType(this TestMessage testMessage, ODataFormat format, ODataPayloadKind payloadKind) { string contentType = TestMediaTypeUtils.GetDefaultContentType(payloadKind, format); testMessage.SetHeader(ODataConstants.ContentTypeHeader, contentType); }
/// <summary> /// Constructs an ODataSerializer that can generate OData payload of the specified kind. /// </summary> /// <param name="payloadKind">The kind of OData payload that this serializer generates.</param> protected ODataSerializer(ODataPayloadKind payloadKind) { ODataPayloadKindHelper.Validate(payloadKind, "payloadKind"); ODataPayloadKind = payloadKind; }
internal static Task<ODataInputContext> CreateAsync(ODataFormat format, ODataMessage message, Encoding encoding, ODataMessageReaderSettings messageReaderSettings, ODataVersion version, bool readingResponse, IEdmModel model, IODataUrlResolver urlResolver, ODataPayloadKind readerPayloadKind) { return message.GetStreamAsync().FollowOnSuccessWith<System.IO.Stream, ODataInputContext>(streamTask => new ODataRawInputContext(format, streamTask.Result, encoding, messageReaderSettings, version, readingResponse, false, model, urlResolver, readerPayloadKind)); }
/// <summary> /// Get the supported media types for a payload kind. /// </summary> /// <param name="kind">The <see cref="ODataPayloadKind"/> to get the supported media types for.</param> /// <param name="includeApplicationJson">true if application/json should be included as supported media type (for reading versions < V3).</param> /// <param name="includeApplicationJsonLight">true if JsonLight media types should be included.</param> /// <returns>The string concatenating all supported media types for <paramref name="kind"/>.</returns> public static string GetSupportedMediaTypes(ODataPayloadKind kind, bool includeApplicationJson = true, bool includeApplicationJsonLight = true) { StringBuilder builder = new StringBuilder(); bool hasTailingComma = false; // Add the JSON media types to the supported payload kinds switch (kind) { case ODataPayloadKind.ResourceSet: case ODataPayloadKind.Resource: case ODataPayloadKind.Property: case ODataPayloadKind.Collection: case ODataPayloadKind.EntityReferenceLink: case ODataPayloadKind.EntityReferenceLinks: case ODataPayloadKind.Error: case ODataPayloadKind.ServiceDocument: case ODataPayloadKind.Parameter: AddJsonMediaTypes(includeApplicationJson, includeApplicationJsonLight, builder); break; default: break; } switch (kind) { case ODataPayloadKind.ResourceSet: case ODataPayloadKind.EntityReferenceLinks: break; case ODataPayloadKind.Resource: break; case ODataPayloadKind.Property: break; case ODataPayloadKind.Collection: break; case ODataPayloadKind.Value: builder.Append("text/plain"); break; case ODataPayloadKind.BinaryValue: builder.Append("application/octet-stream"); break; case ODataPayloadKind.EntityReferenceLink: break; case ODataPayloadKind.Error: break; case ODataPayloadKind.ServiceDocument: break; case ODataPayloadKind.Batch: builder.Append("multipart/mixed, "); AddJsonMediaTypes(includeApplicationJson, includeApplicationJsonLight, builder); hasTailingComma = true; break; case ODataPayloadKind.MetadataDocument: break; case ODataPayloadKind.Parameter: builder.Append(string.Empty); break; case ODataPayloadKind.Unsupported: default: throw new NotSupportedException("Unsupported payload kind found: " + kind.ToString()); } return(hasTailingComma ? builder.ToString(0, builder.Length - 1) : builder.ToString()); }
/// <summary> /// Constructor. /// </summary> /// <param name="payloadKind">The detected payload kind.</param> /// <param name="format">The format for the detected payload kind.</param> internal ODataPayloadKindDetectionResult(ODataPayloadKind payloadKind, ODataFormat format) { DebugUtils.CheckNoExternalCallers(); this.payloadKind = payloadKind; this.format = format; }
private static bool IgnoreTestCase(ODataPayloadKind payloadKind, ReaderTestConfiguration testConfiguration) { // TODO: enable unsupported payload kinds when implemented if (payloadKind == ODataPayloadKind.MetadataDocument) { return(true); } // ignore some payloads in requests since they are not allowed if (testConfiguration.IsRequest) { if (payloadKind == ODataPayloadKind.ServiceDocument || payloadKind == ODataPayloadKind.Error || payloadKind == ODataPayloadKind.EntityReferenceLinks) { // not allowed in requests return(true); } } else { if (payloadKind == ODataPayloadKind.Parameter) { // not allowed in responses return(true); } } ODataFormat format = testConfiguration.Format; // ignore some payloads in some formats switch (payloadKind) { case ODataPayloadKind.Feed: return(format == null); case ODataPayloadKind.Entry: return(format == null); case ODataPayloadKind.Property: return(format == null); case ODataPayloadKind.EntityReferenceLink: return(format == null); case ODataPayloadKind.EntityReferenceLinks: return(format == null); case ODataPayloadKind.Value: return(format != null); case ODataPayloadKind.BinaryValue: return(format != null); case ODataPayloadKind.Collection: return(format == null); case ODataPayloadKind.ServiceDocument: return(format == null); case ODataPayloadKind.MetadataDocument: return(format != null); case ODataPayloadKind.Error: return(format == null); case ODataPayloadKind.Batch: return(format != null); case ODataPayloadKind.Parameter: return(format != ODataFormat.Json); case ODataPayloadKind.Unsupported: // fall through default: return(true); } }
/// <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> /// Constructor. /// </summary> /// <param name="resolver">The media type resolver to use.</param> /// <param name="payloadKind">Kind of the payload.</param> /// <param name="contentTypeName">Name of content type.</param> public MatchInfoCacheKey(ODataMediaTypeResolver resolver, ODataPayloadKind payloadKind, string contentTypeName) { this.MediaTypeResolver = resolver; this.PayloadKind = payloadKind; this.ContentTypeName = contentTypeName; }
/// <summary> /// Sets the content-type and data service version headers on the message used by the message writer. /// This method can be called if it is important to set all the message headers before calling any of the /// write methods. /// If it is sufficient to set the headers when the write methods on the message writer /// are called, you don't have to call this method and setting the headers will happen automatically. /// </summary> /// <param name="payloadKind">The kind of payload to be written with the message writer.</param> /// <returns>The <see cref="ODataFormat"/> used for the specified <paramref name="payloadKind"/>.</returns> public ODataFormat SetHeadersForPayload(ODataPayloadKind payloadKind) { return(ODataUtils.SetHeadersForPayload(this.messageWriter, payloadKind)); }
protected ODataEntryDeserializer(IEdmTypeReference edmType, ODataPayloadKind payloadKind, ODataDeserializerProvider deserializerProvider) : this(edmType, payloadKind) { DeserializerProvider = deserializerProvider; }
/// <summary>Sets the content-type and OData-Version headers on the message used by the message writer.</summary> /// <returns>The content-type and OData-Version headers on the message used by the message writer.</returns> /// <param name="messageWriter">The message writer to set the headers for.</param> /// <param name="payloadKind">The kind of payload to be written with the message writer.</param> /// <remarks> /// This method can be called if it is important to set all the message headers before calling any of the /// write methods on the <paramref name="messageWriter"/>. /// If it is sufficient to set the headers when the write methods on the <paramref name="messageWriter"/> /// are called, you don't have to call this method and setting the headers will happen automatically. /// </remarks> public static ODataFormat SetHeadersForPayload(ODataMessageWriter messageWriter, ODataPayloadKind payloadKind) { ExceptionUtils.CheckArgumentNotNull(messageWriter, "messageWriter"); if (payloadKind == ODataPayloadKind.Unsupported) { throw new ArgumentException(Strings.ODataMessageWriter_CannotSetHeadersWithInvalidPayloadKind(payloadKind), "payloadKind"); } return(messageWriter.SetHeaders(payloadKind)); }
private ODataPayloadKind ParseContextUriFragment(string fragment, Func <IEdmType, string, IEdmType> clientCustomTypeResolver, bool throwIfMetadataConflict, out bool isUndeclared) { bool hasItemSelector = false; ODataDeltaKind kind = ODataDeltaKind.None; isUndeclared = false; // Deal with /$entity if (fragment.EndsWith(ODataConstants.ContextUriFragmentItemSelector, StringComparison.Ordinal)) { hasItemSelector = true; fragment = fragment.Substring(0, fragment.Length - ODataConstants.ContextUriFragmentItemSelector.Length); } else if (fragment.EndsWith(ODataConstants.ContextUriDeltaResourceSet, StringComparison.Ordinal)) { kind = ODataDeltaKind.ResourceSet; fragment = fragment.Substring(0, fragment.Length - ODataConstants.ContextUriDeltaResourceSet.Length); } else if (fragment.EndsWith(ODataConstants.ContextUriDeletedEntry, StringComparison.Ordinal)) { kind = ODataDeltaKind.DeletedEntry; fragment = fragment.Substring(0, fragment.Length - ODataConstants.ContextUriDeletedEntry.Length); } else if (fragment.EndsWith(ODataConstants.ContextUriDeltaLink, StringComparison.Ordinal)) { kind = ODataDeltaKind.Link; fragment = fragment.Substring(0, fragment.Length - ODataConstants.ContextUriDeltaLink.Length); } else if (fragment.EndsWith(ODataConstants.ContextUriDeletedLink, StringComparison.Ordinal)) { kind = ODataDeltaKind.DeletedLink; fragment = fragment.Substring(0, fragment.Length - ODataConstants.ContextUriDeletedLink.Length); } this.parseResult.DeltaKind = kind; // Deal with query option if (fragment.EndsWith(")", StringComparison.Ordinal)) { int index = fragment.Length - 2; for (int rcount = 1; rcount > 0 && index > 0; --index) { switch (fragment[index]) { case '(': rcount--; break; case ')': rcount++; break; } } if (index == 0) { throw new ODataException(ODataErrorStrings.ODataJsonLightContextUriParser_InvalidContextUrl(UriUtils.UriToString(this.parseResult.ContextUri))); } string previous = fragment.Substring(0, index + 1); // Don't treat Collection(Edm.Type) as SelectExpand segment if (!previous.Equals("Collection", StringComparison.Ordinal)) { string selectExpandStr = fragment.Substring(index + 2); selectExpandStr = selectExpandStr.Substring(0, selectExpandStr.Length - 1); // Do not treat Key as SelectExpand segment if (KeyPattern.IsMatch(selectExpandStr)) { throw new ODataException(ODataErrorStrings.ODataJsonLightContextUriParser_LastSegmentIsKeySegment(UriUtils.UriToString(this.parseResult.ContextUri))); } this.parseResult.SelectQueryOption = ExtractSelectQueryOption(selectExpandStr); fragment = previous; } } ODataPayloadKind detectedPayloadKind = ODataPayloadKind.Unsupported; EdmTypeResolver edmTypeResolver = new EdmTypeReaderResolver(this.model, clientCustomTypeResolver); if (!fragment.Contains(ODataConstants.UriSegmentSeparator) && !hasItemSelector && kind == ODataDeltaKind.None) { // Service document: no fragment if (fragment.Length == 0) { detectedPayloadKind = ODataPayloadKind.ServiceDocument; } else if (fragment.Equals(ODataConstants.CollectionPrefix + "(" + ODataConstants.EntityReferenceSegmentName + ")", StringComparison.Ordinal)) { detectedPayloadKind = ODataPayloadKind.EntityReferenceLinks; } else if (fragment.Equals(ODataConstants.EntityReferenceSegmentName, StringComparison.Ordinal)) { detectedPayloadKind = ODataPayloadKind.EntityReferenceLink; } else { var foundNavigationSource = this.model.FindDeclaredNavigationSource(fragment); if (foundNavigationSource != null) { // Resource Set: {schema.entity-container.entity-set} or Singleton: {schema.entity-container.singleton} this.parseResult.NavigationSource = foundNavigationSource; this.parseResult.EdmType = edmTypeResolver.GetElementType(foundNavigationSource); detectedPayloadKind = foundNavigationSource is IEdmSingleton ? ODataPayloadKind.Resource : ODataPayloadKind.ResourceSet; } else { // Property: {schema.type} or Collection({schema.type}) where schema.type is primitive or complex. detectedPayloadKind = this.ResolveType(fragment, clientCustomTypeResolver, throwIfMetadataConflict); Debug.Assert( this.parseResult.EdmType.TypeKind == EdmTypeKind.Primitive || this.parseResult.EdmType.TypeKind == EdmTypeKind.Enum || this.parseResult.EdmType.TypeKind == EdmTypeKind.TypeDefinition || this.parseResult.EdmType.TypeKind == EdmTypeKind.Complex || this.parseResult.EdmType.TypeKind == EdmTypeKind.Collection || this.parseResult.EdmType.TypeKind == EdmTypeKind.Entity || this.parseResult.EdmType.TypeKind == EdmTypeKind.Untyped, "The first context URI segment must be a set or a non-entity type."); } } } else { Debug.Assert(this.parseResult.MetadataDocumentUri.IsAbsoluteUri, "this.parseResult.MetadataDocumentUri.IsAbsoluteUri"); string metadataDocumentStr = UriUtils.UriToString(this.parseResult.MetadataDocumentUri); if (!metadataDocumentStr.EndsWith(ODataConstants.UriMetadataSegment, StringComparison.Ordinal)) { throw new ODataException(ODataErrorStrings.ODataJsonLightContextUriParser_InvalidContextUrl(UriUtils.UriToString(this.parseResult.ContextUri))); } Uri serviceRoot = new Uri(metadataDocumentStr.Substring(0, metadataDocumentStr.Length - ODataConstants.UriMetadataSegment.Length)); ODataUriParser odataUriParser = new ODataUriParser(this.model, serviceRoot, new Uri(serviceRoot, fragment)); ODataPath path; try { path = odataUriParser.ParsePath(); } catch (ODataException) { throw new ODataException(ODataErrorStrings.ODataJsonLightContextUriParser_InvalidContextUrl(UriUtils.UriToString(this.parseResult.ContextUri))); } if (path.Count == 0) { throw new ODataException(ODataErrorStrings.ODataJsonLightContextUriParser_InvalidContextUrl(UriUtils.UriToString(this.parseResult.ContextUri))); } this.parseResult.Path = path; parseResult.NavigationSource = path.NavigationSource(); parseResult.EdmType = path.LastSegment.EdmType; ODataPathSegment lastSegment = path.TrimEndingTypeSegment().LastSegment; if (lastSegment is EntitySetSegment || lastSegment is NavigationPropertySegment) { if (kind != ODataDeltaKind.None) { detectedPayloadKind = ODataPayloadKind.Delta; } else { detectedPayloadKind = hasItemSelector ? ODataPayloadKind.Resource : ODataPayloadKind.ResourceSet; } if (this.parseResult.EdmType is IEdmCollectionType) { var collectionTypeReference = this.parseResult.EdmType.ToTypeReference().AsCollection(); if (collectionTypeReference != null) { this.parseResult.EdmType = collectionTypeReference.ElementType().Definition; } } } else if (lastSegment is SingletonSegment) { detectedPayloadKind = ODataPayloadKind.Resource; } else if (path.IsIndividualProperty()) { isUndeclared = path.IsUndeclared(); detectedPayloadKind = ODataPayloadKind.Property; IEdmComplexType complexType = parseResult.EdmType as IEdmComplexType; if (complexType != null) { detectedPayloadKind = ODataPayloadKind.Resource; } else { IEdmCollectionType collectionType = parseResult.EdmType as IEdmCollectionType; if (collectionType != null) { if (collectionType.ElementType.IsComplex()) { this.parseResult.EdmType = collectionType.ElementType.Definition; detectedPayloadKind = ODataPayloadKind.ResourceSet; } else { detectedPayloadKind = ODataPayloadKind.Collection; } } } } else { throw new ODataException(ODataErrorStrings.ODataJsonLightContextUriParser_InvalidContextUrl(UriUtils.UriToString(this.parseResult.ContextUri))); } } return(detectedPayloadKind); }
protected ODataEntryDeserializer(IEdmTypeReference edmType, ODataPayloadKind payloadKind) : base(edmType, payloadKind) { }
/// <summary> /// Verifies that the result of the test (the message reader) is what the test expected. /// </summary> /// <param name="messageReader">The message reader which is the result of the test. This method should use it to read the results /// of the parsing and verify those.</param> /// <param name="payloadKind">The payload kind specified in the test descriptor.</param> /// <param name="testConfiguration">The test configuration to use.</param> public abstract void VerifyResult( ODataMessageReaderTestWrapper messageReader, ODataPayloadKind payloadKind, ReaderTestConfiguration testConfiguration);
/// <summary> /// Given the Accept and the Accept-Charset headers of the request message computes the media type, encoding and <see cref="ODataFormat"/> /// to be used for the response message. /// </summary> /// <param name="settings">The message writer settings to use for serializing the response payload.</param> /// <param name="payloadKind">The kind of payload to be serialized as part of the response message.</param> /// <param name="mediaTypeResolver">The media type resolver to use when interpreting the content type.</param> /// <param name="mediaType">The media type to be used in the response message.</param> /// <param name="encoding">The encoding to be used in the response message.</param> /// <returns>The <see cref="ODataFormat"/> used when serializing the response.</returns> internal static ODataFormat GetContentTypeFromSettings( ODataMessageWriterSettings settings, ODataPayloadKind payloadKind, ODataMediaTypeResolver mediaTypeResolver, out ODataMediaType mediaType, out Encoding encoding) { Debug.Assert(settings != null, "settings != null"); // compute format, media type and encoding ODataFormat format; // get the supported and default media types for the specified payload kind IList <ODataMediaTypeFormat> supportedMediaTypes = mediaTypeResolver.GetMediaTypeFormats(payloadKind).ToList(); if (supportedMediaTypes == null || supportedMediaTypes.Count == 0) { throw new ODataContentTypeException(Strings.MediaTypeUtils_DidNotFindMatchingMediaType(null, settings.AcceptableMediaTypes)); } if (settings.UseFormat == true) { Debug.Assert(settings.AcceptableMediaTypes == null, "settings.AcceptableMediaTypes == null"); Debug.Assert(settings.AcceptableCharsets == null, "settings.AcceptableCharsets == null"); mediaType = GetDefaultMediaType(supportedMediaTypes, settings.Format, out format); // NOTE the default media types don't have any parameters (in particular no 'charset' parameters) encoding = mediaType.SelectEncoding(); } else { // parse the accept header into its parts IList <KeyValuePair <ODataMediaType, string> > specifiedTypes = HttpUtils.MediaTypesFromString(settings.AcceptableMediaTypes); // Starting in V3 we replace all occurrences of application/json with application/json;odata.metadata=minimal // before handing the acceptable media types to the conneg code. This is necessary because for an accept // header 'application/json, we want to the result to be 'application/json;odata.metadata=minimal' ConvertApplicationJsonInAcceptableMediaTypes(specifiedTypes); ODataMediaTypeFormat selectedMediaTypeWithFormat; string specifiedCharset = null; if (specifiedTypes == null || specifiedTypes.Count == 0) { selectedMediaTypeWithFormat = supportedMediaTypes[0]; } else { // match the specified media types against the supported/default ones and get the format MediaTypeMatchInfo matchInfo = MatchMediaTypes(specifiedTypes.Select(kvp => kvp.Key), supportedMediaTypes.Select(smt => smt.MediaType).ToArray()); if (matchInfo == null) { // We're calling the ToArray here since not all platforms support the string.Join which takes IEnumerable. string supportedTypesAsString = String.Join(", ", supportedMediaTypes.Select(mt => mt.MediaType.ToText()).ToArray()); throw new ODataContentTypeException(Strings.MediaTypeUtils_DidNotFindMatchingMediaType(supportedTypesAsString, settings.AcceptableMediaTypes)); } selectedMediaTypeWithFormat = supportedMediaTypes[matchInfo.TargetTypeIndex]; specifiedCharset = specifiedTypes[matchInfo.SourceTypeIndex].Value; } format = selectedMediaTypeWithFormat.Format; mediaType = selectedMediaTypeWithFormat.MediaType; // If a charset was specified with the accept header, consider it for the encoding string acceptableCharsets = settings.AcceptableCharsets; if (specifiedCharset != null) { acceptableCharsets = acceptableCharsets == null ? specifiedCharset : specifiedCharset + "," + acceptableCharsets; } encoding = GetEncoding(acceptableCharsets, payloadKind, mediaType, /*useDefaultEncoding*/ true); } return(format); }
/// <summary> /// Applies the model and validates the context URI against it. /// </summary> /// <param name="expectedPayloadKind">The payload kind we expect the context URI to conform to.</param> /// <param name="clientCustomTypeResolver">The function of client cuetom type resolver.</param> private void ParseContextUri(ODataPayloadKind expectedPayloadKind, Func <IEdmType, string, IEdmType> clientCustomTypeResolver) { bool isUndeclared = false; ODataPayloadKind detectedPayloadKind = this.ParseContextUriFragment(this.parseResult.Fragment, clientCustomTypeResolver, out isUndeclared); // unsupported payload kind indicates that this is during payload kind detection, so we should not fail. bool detectedPayloadKindMatchesExpectation = detectedPayloadKind == expectedPayloadKind || expectedPayloadKind == ODataPayloadKind.Unsupported; if (detectedPayloadKind == ODataPayloadKind.ResourceSet && this.parseResult.EdmType.IsODataComplexTypeKind()) { this.parseResult.DetectedPayloadKinds = new[] { ODataPayloadKind.ResourceSet, ODataPayloadKind.Property, ODataPayloadKind.Collection }; if (expectedPayloadKind == ODataPayloadKind.Property || expectedPayloadKind == ODataPayloadKind.Collection) { detectedPayloadKindMatchesExpectation = true; } } else if (detectedPayloadKind == ODataPayloadKind.Resource && this.parseResult.EdmType.IsODataComplexTypeKind()) { this.parseResult.DetectedPayloadKinds = new[] { ODataPayloadKind.Resource, ODataPayloadKind.Property }; if (expectedPayloadKind == ODataPayloadKind.Property) { detectedPayloadKindMatchesExpectation = true; } } else if (detectedPayloadKind == ODataPayloadKind.Collection) { // If the detected payload kind is 'collection' it can always also be treated as a property. this.parseResult.DetectedPayloadKinds = new[] { ODataPayloadKind.Collection, ODataPayloadKind.Property }; if (expectedPayloadKind == ODataPayloadKind.Property) { detectedPayloadKindMatchesExpectation = true; } } else if (detectedPayloadKind == ODataPayloadKind.Resource) { this.parseResult.DetectedPayloadKinds = new[] { ODataPayloadKind.Resource, ODataPayloadKind.Delta }; if (expectedPayloadKind == ODataPayloadKind.Delta) { this.parseResult.DeltaKind = ODataDeltaKind.Resource; detectedPayloadKindMatchesExpectation = true; } } else if (detectedPayloadKind == ODataPayloadKind.Property && isUndeclared && (expectedPayloadKind == ODataPayloadKind.Resource || expectedPayloadKind == ODataPayloadKind.ResourceSet)) { // for undeclared, we don't know whether it is a resource/resource set or not. this.parseResult.DetectedPayloadKinds = new[] { expectedPayloadKind, ODataPayloadKind.Property }; detectedPayloadKindMatchesExpectation = true; } else { this.parseResult.DetectedPayloadKinds = new[] { detectedPayloadKind }; } // If the expected and detected payload kinds don't match and we are not running payload kind detection // right now (payloadKind == ODataPayloadKind.Unsupported) and we did not detect a collection kind for // an expected property kind (which is allowed), fail. if (!detectedPayloadKindMatchesExpectation) { throw new ODataException(ODataErrorStrings.ODataJsonLightContextUriParser_ContextUriDoesNotMatchExpectedPayloadKind(UriUtils.UriToString(this.parseResult.ContextUri), expectedPayloadKind.ToString())); } // NOTE: we interpret an empty select query option to mean that nothing should be projected // (whereas a missing select query option means everything should be projected). string selectQueryOption = this.parseResult.SelectQueryOption; if (selectQueryOption != null) { if (detectedPayloadKind != ODataPayloadKind.ResourceSet && detectedPayloadKind != ODataPayloadKind.Resource && detectedPayloadKind != ODataPayloadKind.Delta) { throw new ODataException(ODataErrorStrings.ODataJsonLightContextUriParser_InvalidPayloadKindWithSelectQueryOption(expectedPayloadKind.ToString())); } } }
internal static ODataInputContext Create(ODataFormat format, ODataMessage message, Encoding encoding, ODataMessageReaderSettings messageReaderSettings, ODataVersion version, bool readingResponse, IEdmModel model, IODataUrlResolver urlResolver, ODataPayloadKind readerPayloadKind) { return(new ODataRawInputContext(format, message.GetStream(), encoding, messageReaderSettings, version, readingResponse, true, model, urlResolver, readerPayloadKind)); }
private static ODataPayloadElement CreatePayloadElement(IEdmModel model, ODataPayloadKind payloadKind, ReaderTestConfiguration testConfig) { IEdmEntitySet citySet = model.EntityContainer.FindEntitySet("Cities"); IEdmEntityType cityType = model.EntityTypes().Single(e => e.Name == "CityType"); IEdmProperty cityNameProperty = cityType.Properties().Single(e => e.Name == "Name"); IEdmNavigationProperty policeStationNavProp = cityType.NavigationProperties().Single(e => e.Name == "PoliceStation"); IEdmOperationImport primitiveCollectionResultOperation = model.EntityContainer.FindOperationImports("PrimitiveCollectionResultOperation").Single(); IEdmOperationImport serviceOp1 = model.EntityContainer.FindOperationImports("ServiceOperation1").Single(); bool isRequest = testConfig.IsRequest; bool isJsonLightRequest = isRequest && testConfig.Format == ODataFormat.Json; switch (payloadKind) { case ODataPayloadKind.Feed: { return(PayloadBuilder.EntitySet().WithTypeAnnotation(cityType).ExpectedEntityType(cityType, citySet)); } case ODataPayloadKind.Entry: { return(PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).WithTypeAnnotation(cityType).ExpectedEntityType(cityType, citySet)); } case ODataPayloadKind.Property: return(PayloadBuilder.PrimitiveProperty(isJsonLightRequest ? string.Empty : null, "SomeCityValue").ExpectedProperty(cityType, "Name")); case ODataPayloadKind.EntityReferenceLink: return(PayloadBuilder.DeferredLink("http://odata.org/entityreferencelink").ExpectedNavigationProperty(citySet, cityType, "PoliceStation")); case ODataPayloadKind.EntityReferenceLinks: return(PayloadBuilder.LinkCollection().Item(PayloadBuilder.DeferredLink("http://odata.org/entityreferencelink")).ExpectedNavigationProperty((EdmEntitySet)citySet, (EdmEntityType)cityType, "CityHall")); case ODataPayloadKind.Value: return(PayloadBuilder.PrimitiveValue("PrimitiveValue")); case ODataPayloadKind.BinaryValue: return(PayloadBuilder.PrimitiveValue(new byte[] { 0, 0, 1, 1 })); case ODataPayloadKind.Collection: return(PayloadBuilder.PrimitiveCollection().CollectionName(null).ExpectedFunctionImport((EdmOperationImport)primitiveCollectionResultOperation)); case ODataPayloadKind.ServiceDocument: Debug.Assert(!isRequest, "Not supported in requests."); return(new ServiceDocumentInstance().Workspace(PayloadBuilder.Workspace())); case ODataPayloadKind.MetadataDocument: Debug.Assert(!isRequest, "Not supported in requests."); throw new NotImplementedException(); case ODataPayloadKind.Error: Debug.Assert(!isRequest, "Not supported in requests."); return(PayloadBuilder.Error("ErrorCode")); case ODataPayloadKind.Parameter: // build parameter payload based on model definition var parameterPayload = new ComplexInstance(null, false); ODataPayloadElement a = PayloadBuilder.PrimitiveValue(123).WithTypeAnnotation(EdmCoreModel.Instance.GetInt32(false)); ODataPayloadElement b = PayloadBuilder.PrimitiveValue("stringvalue").WithTypeAnnotation(EdmCoreModel.Instance.GetString(false)); PrimitiveProperty parametera = new PrimitiveProperty("a", "Edm.Integer", ((PrimitiveValue)a).ClrValue); PrimitiveProperty parameterb = new PrimitiveProperty("b", "Edm.String", ((PrimitiveValue)b).ClrValue); parameterPayload.Add(parametera); parameterPayload.Add(parameterb); parameterPayload.ExpectedFunctionImport((EdmOperationImport)serviceOp1); return(parameterPayload); case ODataPayloadKind.Unsupported: // fall through default: throw new NotSupportedException(); } }
private void DetectStartArrayPayloadKind(bool isTopLevel) { if (!isTopLevel) { this.AddPayloadKinds(new ODataPayloadKind[] { ODataPayloadKind.Property }); } base.JsonReader.StartBuffering(); try { base.JsonReader.ReadStartArray(); switch (base.JsonReader.NodeType) { case JsonNodeType.EndArray: { ODataPayloadKind[] kindArray2 = new ODataPayloadKind[3]; kindArray2[1] = ODataPayloadKind.Collection; kindArray2[2] = ODataPayloadKind.EntityReferenceLinks; this.AddPayloadKinds(kindArray2); return; } case JsonNodeType.Property: return; case JsonNodeType.PrimitiveValue: this.AddPayloadKinds(new ODataPayloadKind[] { ODataPayloadKind.Collection }); return; case JsonNodeType.StartObject: break; default: return; } base.JsonReader.ReadStartObject(); bool flag = false; int num = 0; while (base.JsonReader.NodeType == JsonNodeType.Property) { string strB = base.JsonReader.ReadPropertyName(); num++; if (num > 1) { break; } if ((string.CompareOrdinal("uri", strB) == 0) && (base.JsonReader.NodeType == JsonNodeType.PrimitiveValue)) { flag = true; } base.JsonReader.SkipValue(); } ODataPayloadKind[] payloadKinds = new ODataPayloadKind[2]; payloadKinds[1] = ODataPayloadKind.Collection; this.AddPayloadKinds(payloadKinds); if (flag && (num == 1)) { this.AddPayloadKinds(new ODataPayloadKind[] { ODataPayloadKind.EntityReferenceLinks }); } } finally { base.JsonReader.StopBuffering(); } }
/// <summary> /// Creates an <see cref="ODataMessageReader"/> for a given message and context using /// WCF DS client settings. /// </summary> /// <param name="responseMessage">The response message</param> /// <param name="responseInfo">The response context</param> /// <param name="payloadKind">Type of the message.</param> /// <returns>The message reader.</returns> protected static ODataMessageReader CreateODataMessageReader(IODataResponseMessage responseMessage, ResponseInfo responseInfo, ref ODataPayloadKind payloadKind) { ODataMessageReaderSettings settings = responseInfo.ReadHelper.CreateSettings(); ODataMessageReader odataMessageReader = responseInfo.ReadHelper.CreateReader(responseMessage, settings); if (payloadKind == ODataPayloadKind.Unsupported) { var payloadKinds = odataMessageReader.DetectPayloadKind().ToList(); if (payloadKinds.Count == 0) { throw DSClient.Error.InvalidOperation(DSClient.Strings.AtomMaterializer_InvalidResponsePayload(XmlConstants.DataWebNamespace)); } // Pick the first payload kind detected by ODataLib and use that to parse the exception. // The only exception being payload with entity reference link(s). If one of the payload kinds // is reference links, then we need to give preference to reference link payloads. ODataPayloadKindDetectionResult detectionResult = payloadKinds.FirstOrDefault(k => k.PayloadKind == ODataPayloadKind.EntityReferenceLink || k.PayloadKind == ODataPayloadKind.EntityReferenceLinks); if (detectionResult == null) { detectionResult = payloadKinds.First(); } if (detectionResult.Format != ODataFormat.Json && detectionResult.Format != ODataFormat.RawValue) { throw DSClient.Error.InvalidOperation(DSClient.Strings.AtomMaterializer_InvalidContentTypeEncountered(responseMessage.GetHeader(XmlConstants.HttpContentType))); } payloadKind = detectionResult.PayloadKind; } return(odataMessageReader); }
protected ODataEntryDeserializer(IEdmTypeReference edmType, ODataPayloadKind payloadKind, ODataDeserializerProvider deserializerProvider) : base(edmType, payloadKind, deserializerProvider) { }
/// <summary> /// Determine the <see cref="ODataFormat"/> to use for the given <paramref name="contentTypeName"/>. If no supported content type /// is found an exception is thrown. /// </summary> /// <param name="contentTypeName">The name of the content type to be checked.</param> /// <param name="supportedPayloadKinds">All possible kinds of payload that can be read with this content type.</param> /// <param name="mediaTypeResolver">The media type resolver to use when interpreting the content type.</param> /// <param name="mediaType">The media type parsed from the <paramref name="contentTypeName"/>.</param> /// <param name="encoding">The encoding from the content type or the default encoding for the <paramref name="mediaType" />.</param> /// <param name="selectedPayloadKind"> /// The payload kind that was selected form the list of <paramref name="supportedPayloadKinds"/> for the /// specified <paramref name="contentTypeName"/>. /// </param> /// <returns>The <see cref="ODataFormat"/> for the <paramref name="contentTypeName"/>.</returns> internal static ODataFormat GetFormatFromContentType(string contentTypeName, ODataPayloadKind[] supportedPayloadKinds, ODataMediaTypeResolver mediaTypeResolver, out ODataMediaType mediaType, out Encoding encoding, out ODataPayloadKind selectedPayloadKind) { Debug.Assert(!supportedPayloadKinds.Contains(ODataPayloadKind.Unsupported), "!supportedPayloadKinds.Contains(ODataPayloadKind.Unsupported)"); string charset; mediaType = ParseContentType(contentTypeName, out charset); IList <ODataMediaTypeFormat> supportedMediaTypes = null; for (int i = 0; i < supportedPayloadKinds.Length; ++i) { // get the supported and default media types for the current payload kind ODataPayloadKind supportedPayloadKind = supportedPayloadKinds[i]; supportedMediaTypes = mediaTypeResolver.GetMediaTypeFormats(supportedPayloadKind).ToList(); // match the specified media types against the supported/default ones // and get the format var cacheKey = new MatchInfoCacheKey(mediaTypeResolver, supportedPayloadKind, contentTypeName); MediaTypeMatchInfo matchInfo; if (!MatchInfoCache.TryGetValue(cacheKey, out matchInfo)) { matchInfo = MatchMediaTypes(supportedMediaTypes.Select(smt => smt.MediaType), new[] { mediaType }); MatchInfoCache.Add(cacheKey, matchInfo); } if (matchInfo != null) { Debug.Assert(matchInfo.TargetTypeIndex == 0, "Invalid target type index detected."); selectedPayloadKind = supportedPayloadKind; encoding = GetEncoding(charset, selectedPayloadKind, mediaType, /*useDefaultEncoding*/ false); return(supportedMediaTypes[matchInfo.SourceTypeIndex].Format); } } // We're calling the ToArray here since not all platforms support the string.Join which takes IEnumerable. string supportedTypesAsString = String.Join(", ", supportedPayloadKinds.SelectMany(pk => mediaTypeResolver.GetMediaTypeFormats(pk).Select(mt => mt.MediaType.ToText())).ToArray()); throw new ODataContentTypeException(Strings.MediaTypeUtils_CannotDetermineFormatFromContentType(supportedTypesAsString, contentTypeName)); }
/// <summary> /// Initializes a new instance of the <see cref="ODataDeserializer"/> class. /// </summary> /// <param name="payloadKind">The kind of payload this deserializer handles.</param> protected ODataDeserializer(ODataPayloadKind payloadKind) { ODataPayloadKind = payloadKind; }
internal static Task <ODataInputContext> CreateAsync(ODataFormat format, ODataMessage message, Encoding encoding, ODataMessageReaderSettings messageReaderSettings, ODataVersion version, bool readingResponse, IEdmModel model, IODataUrlResolver urlResolver, ODataPayloadKind readerPayloadKind) { return(message.GetStreamAsync().FollowOnSuccessWith <System.IO.Stream, ODataInputContext>(streamTask => new ODataRawInputContext(format, streamTask.Result, encoding, messageReaderSettings, version, readingResponse, false, model, urlResolver, readerPayloadKind))); }
internal static MaterializeAtom Materialize(ResponseInfo responseInfo, System.Data.Services.Client.QueryComponents queryComponents, ProjectionPlan plan, string contentType, IODataResponseMessage message, ODataPayloadKind expectedPayloadKind) { if ((message.StatusCode != 0xcc) && !string.IsNullOrEmpty(contentType)) { return(new MaterializeAtom(responseInfo, queryComponents, plan, message, expectedPayloadKind)); } return(MaterializeAtom.EmptyResults); }
public void CanReadType_ForTypeless_ReturnsExpectedResult_DependingOnODataPathAndPayloadKind(ODataPath path, ODataPayloadKind payloadKind) { // Arrange IEnumerable <ODataPayloadKind> allPayloadKinds = Enum.GetValues(typeof(ODataPayloadKind)).Cast <ODataPayloadKind>(); var model = CreateModel(); var request = CreateFakeODataRequest(model); request.ODataProperties().Path = path; var formatterWithGivenPayload = new ODataMediaTypeFormatter(new[] { payloadKind }) { Request = request }; var formatterWithoutGivenPayload = new ODataMediaTypeFormatter(allPayloadKinds.Except(new[] { payloadKind })) { Request = request }; // Act & Assert Assert.True(formatterWithGivenPayload.CanReadType(typeof(IEdmObject))); Assert.False(formatterWithoutGivenPayload.CanReadType(typeof(IEdmObject))); }
/// <summary> /// Initializes a new instance of the <see cref="ODataEdmTypeSerializer"/> class. /// </summary> /// <param name="payloadKind">The kind of OData payload that this serializer generates.</param> protected ODataEdmTypeSerializer(ODataPayloadKind payloadKind) : base(payloadKind) { }
/// <summary> /// Gets the default content type for a given payload kind and format. /// </summary> /// <param name="kind">The payload kind to get the default format for.</param> /// <param name="format">The format from the test configuration.</param> /// <returns>The default content type used by the message writer.</returns> public static string GetDefaultContentType(ODataPayloadKind kind, ODataFormat format) { switch (kind) { case ODataPayloadKind.ResourceSet: case ODataPayloadKind.EntityReferenceLinks: if (format == ODataFormat.Json) { return("application/json;odata.metadata=minimal;odata.streaming=true;charset=utf-8"); } else { throw new NotSupportedException("Unsupported format for " + kind.ToString() + "."); } case ODataPayloadKind.Resource: if (format == ODataFormat.Json) { return("application/json;odata.metadata=minimal;odata.streaming=true;charset=utf-8"); } else { throw new NotSupportedException("Unsupported format for " + kind.ToString() + "."); } case ODataPayloadKind.Value: if (format == ODataFormat.RawValue || format == null) { return("text/plain;charset=iso-8859-1"); } else { throw new NotSupportedException("Unsupported format for " + kind.ToString() + "."); } case ODataPayloadKind.BinaryValue: if (format == ODataFormat.RawValue || format == null) { return("application/octet-stream"); } else { throw new NotSupportedException("Unsupported format for " + kind.ToString() + "."); } case ODataPayloadKind.Property: // fall through case ODataPayloadKind.Collection: // fall through case ODataPayloadKind.EntityReferenceLink: // fall through case ODataPayloadKind.Error: // fall through case ODataPayloadKind.ServiceDocument: if (format == ODataFormat.Json) { return("application/json;odata.metadata=minimal;odata.streaming=true;charset=utf-8"); } else { throw new NotSupportedException("Unsupported format for " + kind.ToString() + "."); } case ODataPayloadKind.Batch: if (format == ODataFormat.Batch || format == null) { return("multipart/mixed"); } else { throw new NotSupportedException("Unsupported format for " + kind.ToString() + "."); } case ODataPayloadKind.MetadataDocument: if (format == ODataFormat.Metadata || format == null) { return("application/xml"); } else { throw new NotSupportedException("Unsupported format for " + kind.ToString() + "."); } case ODataPayloadKind.Parameter: if (format == ODataFormat.Json) { return("application/json;odata.metadata=minimal;odata.streaming=true;charset=utf-8"); } else { throw new NotSupportedException("Unsupported format for " + kind.ToString() + "."); } case ODataPayloadKind.Unsupported: default: throw new NotSupportedException("Unsupported payload kind found: " + kind.ToString()); } }
/// <summary> /// Gets the supported media types and formats for the given payload kind. /// </summary> /// <param name="payloadKind">The payload kind to get media types for.</param> /// <returns>An array of media type / format pairs, sorted by priority.</returns> internal MediaTypeWithFormat[] GetMediaTypesForPayloadKind(ODataPayloadKind payloadKind) { DebugUtils.CheckNoExternalCallers(); return this.mediaTypesForPayloadKind[(int)payloadKind]; }
/// <summary> /// Applies the model and validates the context URI against it. /// </summary> /// <param name="expectedPayloadKind">The payload kind we expect the context URI to conform to.</param> /// <param name="clientCustomTypeResolver">The function of client custom type resolver.</param> /// <param name="throwIfMetadataConflict">Whether to throw if a type specified in the ContextUri is not found in metadata.</param> private void ParseContextUri(ODataPayloadKind expectedPayloadKind, Func <IEdmType, string, IEdmType> clientCustomTypeResolver, bool throwIfMetadataConflict) { bool isUndeclared; ODataPayloadKind detectedPayloadKind = this.ParseContextUriFragment(this.parseResult.Fragment, clientCustomTypeResolver, throwIfMetadataConflict, out isUndeclared); // unsupported payload kind indicates that this is during payload kind detection, so we should not fail. bool detectedPayloadKindMatchesExpectation = detectedPayloadKind == expectedPayloadKind || expectedPayloadKind == ODataPayloadKind.Unsupported; IEdmType parseType = this.parseResult.EdmType; if (parseType != null && parseType.TypeKind == EdmTypeKind.Untyped) { if (string.Equals(parseType.FullTypeName(), ODataConstants.ContextUriFragmentUntyped, StringComparison.Ordinal)) { // Anything matches the built-in Edm.Untyped this.parseResult.DetectedPayloadKinds = new[] { ODataPayloadKind.ResourceSet, ODataPayloadKind.Property, ODataPayloadKind.Collection, ODataPayloadKind.Resource }; detectedPayloadKindMatchesExpectation = true; } else if (expectedPayloadKind == ODataPayloadKind.Property || expectedPayloadKind == ODataPayloadKind.Resource) { // If we created an untyped type because the name was not resolved it can match any single value this.parseResult.DetectedPayloadKinds = new[] { ODataPayloadKind.Property, ODataPayloadKind.Resource }; detectedPayloadKindMatchesExpectation = true; } } else if (parseType != null && parseType.TypeKind == EdmTypeKind.Collection && ((IEdmCollectionType)parseType).ElementType.TypeKind() == EdmTypeKind.Untyped) { this.parseResult.DetectedPayloadKinds = new[] { ODataPayloadKind.ResourceSet, ODataPayloadKind.Property, ODataPayloadKind.Collection }; if (expectedPayloadKind == ODataPayloadKind.ResourceSet || expectedPayloadKind == ODataPayloadKind.Property || expectedPayloadKind == ODataPayloadKind.Collection) { detectedPayloadKindMatchesExpectation = true; } } else if (detectedPayloadKind == ODataPayloadKind.ResourceSet && parseType.IsODataComplexTypeKind()) { this.parseResult.DetectedPayloadKinds = new[] { ODataPayloadKind.ResourceSet, ODataPayloadKind.Property, ODataPayloadKind.Collection }; if (expectedPayloadKind == ODataPayloadKind.Property || expectedPayloadKind == ODataPayloadKind.Collection) { detectedPayloadKindMatchesExpectation = true; } } else if (detectedPayloadKind == ODataPayloadKind.Resource && parseType.IsODataComplexTypeKind()) { this.parseResult.DetectedPayloadKinds = new[] { ODataPayloadKind.Resource, ODataPayloadKind.Property }; if (expectedPayloadKind == ODataPayloadKind.Property || expectedPayloadKind == ODataPayloadKind.Delta) { detectedPayloadKindMatchesExpectation = true; } } else if (detectedPayloadKind == ODataPayloadKind.Collection) { // If the detected payload kind is 'collection' it can always also be treated as a property. this.parseResult.DetectedPayloadKinds = new[] { ODataPayloadKind.Collection, ODataPayloadKind.Property }; if (expectedPayloadKind == ODataPayloadKind.Property) { detectedPayloadKindMatchesExpectation = true; } } else if (detectedPayloadKind == ODataPayloadKind.Resource) { this.parseResult.DetectedPayloadKinds = new[] { ODataPayloadKind.Resource, ODataPayloadKind.Delta }; if (expectedPayloadKind == ODataPayloadKind.Delta) { this.parseResult.DeltaKind = ODataDeltaKind.Resource; detectedPayloadKindMatchesExpectation = true; } } else if (detectedPayloadKind == ODataPayloadKind.Property && isUndeclared && (expectedPayloadKind == ODataPayloadKind.Resource || expectedPayloadKind == ODataPayloadKind.ResourceSet)) { // for undeclared, we don't know whether it is a resource/resource set or not. this.parseResult.DetectedPayloadKinds = new[] { expectedPayloadKind, ODataPayloadKind.Property }; detectedPayloadKindMatchesExpectation = true; } else { this.parseResult.DetectedPayloadKinds = new[] { detectedPayloadKind }; } // If the expected and detected payload kinds don't match and we are not running payload kind detection // right now (payloadKind == ODataPayloadKind.Unsupported) and we did not detect a collection kind for // an expected property kind (which is allowed), fail. if (!detectedPayloadKindMatchesExpectation) { throw new ODataException(ODataErrorStrings.ODataJsonLightContextUriParser_ContextUriDoesNotMatchExpectedPayloadKind(UriUtils.UriToString(this.parseResult.ContextUri), expectedPayloadKind.ToString())); } // NOTE: we interpret an empty select query option to mean that nothing should be projected // (whereas a missing select query option means everything should be projected). string selectQueryOption = this.parseResult.SelectQueryOption; if (selectQueryOption != null) { if (detectedPayloadKind != ODataPayloadKind.ResourceSet && detectedPayloadKind != ODataPayloadKind.Resource && detectedPayloadKind != ODataPayloadKind.Delta) { throw new ODataException(ODataErrorStrings.ODataJsonLightContextUriParser_InvalidPayloadKindWithSelectQueryOption(expectedPayloadKind.ToString())); } } }