public void AddObjectTestAction(ODataFormat format, MergeOption mergeOption, SaveChangesOptions saveChangesOption) { DataServiceContextWrapper <DefaultContainer> contextWrapper = this.CreateContext(); contextWrapper.Context.MergeOption = mergeOption; if (format == ODataFormat.Json) { contextWrapper.Format.UseJson(); } contextWrapper.Configurations.RequestPipeline .OnEntryStarting(PipelineEventsTestsHelper.ModifyPropertyValueCustomerEntity_Writing) .OnEntryEnding(PipelineEventsTestsHelper.ModifyPropertyValueCustomerEntry_Writing); Customer customer = PipelineEventsTestsHelper.CreateNewCustomer(100); contextWrapper.AddObject("Customer", customer); contextWrapper.SaveChanges(saveChangesOption); if (format == ODataFormat.Atom) { // Make the ATOM payload order consistence with JSON. Assert.IsTrue(customer.Name.EndsWith("UpdatedODataEntryPropertyValueModifyPropertyValueCustomerEntry_Writing"), "Unexpected primitive property"); } else { Assert.IsTrue(customer.Name.EndsWith("UpdatedODataEntryPropertyValue"), "Unexpected primitive property"); } Assert.IsTrue(customer.Auditing.ModifiedBy.Equals("UpdatedODataEntryPropertyValue"), "Unexpected complex property"); Assert.IsTrue(customer.PrimaryContactInfo.EmailBag.Contains("UpdatedODataEntryPropertyValue")); contextWrapper.DeleteObject(customer); contextWrapper.SaveChanges(); }
protected override void VisitRequestOperation(IHttpRequest operation) { var requestOperation = operation as ODataRequest; ExceptionUtilities.CheckObjectNotNull(requestOperation, "Operation must be request"); ODataPayloadElement rootElement = null; string contentType = null; if (requestOperation.Body != null && requestOperation.Body.RootElement != null) { rootElement = requestOperation.Body.RootElement; contentType = requestOperation.GetHeaderValueIfExists(Microsoft.OData.Core.ODataConstants.ContentTypeHeader); } if (rootElement != null) { ODataFormat format = null; if (contentType.Contains(MimeTypes.ApplicationAtomXml)) { format = ODataFormat.Atom; } else if (contentType.Contains(MimeTypes.ApplicationJson)) { format = ODataFormat.Json; } new ExpectedPayloadFixups().Fixup(rootElement, format); } }
/// <summary> /// Creates a new instance of MaterializerEntry using the given entity descriptor for LoadProperty. /// </summary> /// <param name="entityDescriptor">Entity descriptor.</param> /// <param name="format">OData Format.</param> /// <param name="isTracking">Whether this entity is being tracked.</param> /// <remarks>Use this constructor only for LoadProperty scenario.</remarks> private MaterializerEntry(EntityDescriptor entityDescriptor, ODataFormat format, bool isTracking) { this.entityDescriptor = entityDescriptor; this.Format = format; this.isTracking = isTracking; this.SetFlagValue(EntryFlags.ShouldUpdateFromPayload | EntryFlags.EntityHasBeenResolved | EntryFlags.ForLoadProperty, true); }
public static string Generate(PayloadBuilder payloadBuilder, string format) { ODataFormat oDataFormat = null; if (format.StartsWith(UnitTestsUtil.JsonLightMimeType)) { oDataFormat = ODataFormat.Json; } //else if (format.StartsWith(UnitTestsUtil.AtomFormat) || // format.StartsWith(UnitTestsUtil.MimeApplicationXml)) //{ // oDataFormat = ODataFormat.Atom; //} //[Lianw] Remove Atom else if (format.StartsWith(UnitTestsUtil.MimeApplicationXml)) { oDataFormat = ODataFormat.Metadata; } else { Assert.Fail(String.Format("Invalid format specified - {0}", format)); } return(Generate(payloadBuilder, oDataFormat)); }
private ODataAtomOutputContext(ODataFormat format, Stream messageStream, Encoding encoding, ODataMessageWriterSettings messageWriterSettings, bool writingResponse, bool synchronous, IEdmModel model, IODataUrlResolver urlResolver) : base(format, messageWriterSettings, writingResponse, synchronous, model, urlResolver) { try { Stream asynchronousOutputStream; this.messageOutputStream = messageStream; if (synchronous) { asynchronousOutputStream = messageStream; } else { this.asynchronousOutputStream = new AsyncBufferedStream(messageStream); asynchronousOutputStream = this.asynchronousOutputStream; } this.xmlRootWriter = ODataAtomWriterUtils.CreateXmlWriter(asynchronousOutputStream, messageWriterSettings, encoding); this.xmlWriter = this.xmlRootWriter; } catch (Exception exception) { if (ExceptionUtils.IsCatchableExceptionType(exception) && (messageStream != null)) { messageStream.Dispose(); } throw; } }
/// <summary> /// Constructor. /// </summary> /// <param name="innerExpectedResult">The inner <see cref="ReaderTestExpectedResult"/> that is doing most of the work.</param> /// <param name="expectedFormat">The expected <see cref="ODataFormat"/> for the specified content type.</param> /// <param name="settings">Settings to use.</param> public ContentTypeReaderTestExpectedResult(ReaderTestExpectedResult innerExpectedResult, ODataFormat expectedFormat, ReaderTestExpectedResult.ReaderTestExpectedResultSettings settings) : base(settings) { this.innerExpectedResult = innerExpectedResult; this.expectedFormat = expectedFormat; this.settings = settings; }
/// <summary> /// Creates an <see cref="ODataCollectionWriter"/> for the specified message and its stream. /// </summary> /// <param name="format">The serialization format to create the writer for.</param> /// <param name="encoding">The encoding to create the writer with.</param> /// <param name="stream">The response stream to write to.</param> /// <param name="settings">Writer settings to use.</param> /// <param name="metadataProvider">The metadata provider to use.</param> /// <param name="synchronous">True if the writer is created for synchronous operation; false for asynchronous.</param> /// <returns>The newly created <see cref="ODataCollectionWriter"/> instance.</returns> /// <remarks>This is used to create the collection writer once we've obtained the stream from the response.</remarks> private static ODataCollectionWriter CreateCollectionWriter( ODataFormat format, Encoding encoding, Stream stream, ODataWriterSettings settings, DataServiceMetadataProviderWrapper metadataProvider, bool synchronous) { if (settings.BaseUri != null && !settings.BaseUri.IsAbsoluteUri) { throw new ODataException(Strings.ODataWriter_BaseUriMustBeNullOrAbsolute(UriUtils.UriToString(settings.BaseUri))); } switch (format) { case ODataFormat.Json: return(new ODataJsonCollectionWriter(stream, settings, encoding, metadataProvider, synchronous)); case ODataFormat.Atom: return(new ODataAtomCollectionWriter(stream, settings, encoding, metadataProvider, synchronous)); case ODataFormat.Default: Debug.Assert(false, "Should never get here as content-type negotiation should not return Default format for collection."); throw new ODataException(Strings.ODataCollectionWriter_CannotCreateCollectionWriterForFormat(format.ToString())); default: throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataCollectionWriter_CreateCollectionWriter_UnreachableCodePath)); } }
/// <inheritdoc/> public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType) { if (headers == null) { throw Error.ArgumentNull("headers"); } // call base to validate parameters and set Content-Type header based on mediaType parameter. base.SetDefaultContentHeaders(type, headers, mediaType); ODataFormat format = GetODataFormat(headers); IEnumerable <KeyValuePair <string, string> > oDataHeaders = GetResponseMessageHeaders(type, format, _defaultODataVersion); foreach (KeyValuePair <string, string> pair in oDataHeaders) { // Special case Content-Type header so that we don't end up with two values for it // since base.SetDefaultContentHeaders could also have set it. if (String.Equals("Content-Type", pair.Key, StringComparison.OrdinalIgnoreCase)) { headers.ContentType = MediaTypeHeaderValue.Parse(pair.Value); } else { headers.TryAddWithoutValidation(pair.Key, pair.Value); } } }
public void UpdateObjectTestAction(ODataFormat format, MergeOption mergeOption, SaveChangesOptions saveChangesOption) { DataServiceContextWrapper <DefaultContainer> contextWrapper = this.CreateContext(); contextWrapper.Context.MergeOption = mergeOption; contextWrapper.Context.AddAndUpdateResponsePreference = DataServiceResponsePreference.IncludeContent; if (format == ODataFormat.Json) { contextWrapper.Format.UseJson(); } Customer customer = PipelineEventsTestsHelper.CreateNewCustomer(200); contextWrapper.AddObject("Customer", customer); contextWrapper.SaveChanges(); contextWrapper.Configurations.RequestPipeline .OnEntryStarting(PipelineEventsTestsHelper.ModifyPropertyValueCustomerEntity_Writing) .OnEntryEnding(PipelineEventsTestsHelper.ModifyPropertyValueCustomerEntry_Writing); customer.Name = "update"; contextWrapper.UpdateObject(customer); contextWrapper.SaveChanges(saveChangesOption); Assert.IsTrue(customer.Name.EndsWith("UpdatedODataEntryPropertyValue"), "Unexpected primitive property"); Assert.IsTrue(customer.Auditing.ModifiedBy.Equals("UpdatedODataEntryPropertyValue"), "Unexpected complex property"); Assert.IsTrue(customer.PrimaryContactInfo.EmailBag.Contains("UpdatedODataEntryPropertyValue")); contextWrapper.DeleteObject(customer); contextWrapper.SaveChanges(); }
/// <summary> /// Constructor. /// </summary> /// <param name="format">The format used for the test.</param> /// <param name="messageWriterSettings">The message writer settings used for the test.</param> /// <param name="IsRequest">True if the test is writing a request. Otherwise false if it's writing a response.</param> /// <param name="synchronous">True if the test should be ran using synchronous API. Otherwise false if it should be ran using asynchronous APIs.</param> public WriterTestConfiguration(ODataFormat format, ODataMessageWriterSettings messageWriterSettings, bool IsRequest, bool synchronous) : base(format, messageWriterSettings.Version.Value, IsRequest, TestODataBehaviorKind.Default) { Debug.Assert(messageWriterSettings != null, "messageWriterSettings != null"); this.Synchronous = synchronous; this.MessageWriterSettings = messageWriterSettings; }
/// <summary> /// Creates a new instance of the <see cref="PayloadMetadataParameterInterpreter"/> class. /// </summary> /// <param name="format">The response format.</param> /// <returns>A new instance of the <see cref="PayloadMetadataParameterInterpreter"/> class.</returns> internal static PayloadMetadataParameterInterpreter Create(ODataFormatWithParameters format) { ODataFormat odataFormat = format == null ? null : format.Format; string rawParameterValue = format == null ? null : format.GetParameterValue(MediaTypeParameterName); return(new PayloadMetadataParameterInterpreter(odataFormat, rawParameterValue)); }
public void AddBaseUriStringToExpectedDescriptors(string baseUri, ODataFormat format) { if (this.GetExpectedDescriptors(format) != null) { foreach (var expectedDescriptorsForFormat in this.GetExpectedDescriptors(format)) { foreach (MyOperationDescriptor od in expectedDescriptorsForFormat) { if (format == ODataFormat.Json && od.Metadata[0] == '#') { od.Metadata = baseUri + "/$metadata" + od.Metadata; } else if (this.AddBaseUriToMetadata == null || this.AddBaseUriToMetadata.Value) { od.Metadata = baseUri + "/" + od.Metadata; } if (this.AddBaseUriToTarget == null || this.AddBaseUriToTarget.Value) { od.Target = baseUri + "/" + od.Target; } } } } }
/// <summary> /// Visits the root element of the operation. /// </summary> /// <param name="operation">The operation to visit</param> protected override void VisitResponseOperation(HttpResponseData operation) { var responseOperation = operation as ODataResponse; ExceptionUtilities.CheckObjectNotNull(responseOperation, "Operation must be a response"); ODataPayloadElement rootElement = null; string contentType = null; if (responseOperation.RootElement != null) { rootElement = responseOperation.RootElement; contentType = responseOperation.GetHeaderValueIfExists(Microsoft.OData.ODataConstants.ContentTypeHeader); } if (rootElement != null) { ODataFormat format = null; if (contentType.Contains(MimeTypes.ApplicationJson)) { format = ODataFormat.Json; } new ExpectedPayloadFixups().Fixup(rootElement, format); } }
public void TestCustomMediaTypeGetFormatFromContentType() { var resolver = new MyMediaTypeResolver(); foreach (var payloadKind in Enum.GetValues(typeof(ODataPayloadKind)).Cast <ODataPayloadKind>()) { if (payloadKind == ODataPayloadKind.Unsupported) { continue; } string contentType = "text/x-A"; string expectedBoundary = null; ODataMediaType expectedMediaType = MyFormat.MediaTypeWithFormatA.MediaType; if (payloadKind == ODataPayloadKind.Batch) { expectedBoundary = "ba_" + Guid.NewGuid(); contentType += ";boundary=" + expectedBoundary; expectedMediaType = new ODataMediaType("text", "x-A", new KeyValuePair <string, string>("boundary", expectedBoundary)); } ODataMediaType mediaType; Encoding encoding; ODataPayloadKind selectedPayloadKind; string batchBoundary; ODataFormat actual = MediaTypeUtils.GetFormatFromContentType(contentType, new[] { payloadKind }, resolver, out mediaType, out encoding, out selectedPayloadKind, out batchBoundary); Console.WriteLine(payloadKind); actual.ShouldBeEquivalentTo(MyFormat.Instance); mediaType.ShouldBeEquivalentTo(expectedMediaType); encoding.ShouldBeEquivalentTo(payloadKind == ODataPayloadKind.BinaryValue ? null : Encoding.UTF8); selectedPayloadKind.ShouldBeEquivalentTo(payloadKind); batchBoundary.ShouldBeEquivalentTo(expectedBoundary); } }
public void TestCustomMediaTypeGetFormatFromContentType() { var resolver = new MyMediaTypeResolver(); foreach (var payloadKind in Enum.GetValues(typeof(ODataPayloadKind)).Cast <ODataPayloadKind>()) { if (payloadKind == ODataPayloadKind.Unsupported) { continue; } string contentType = "text/x-A"; string expectedBoundary = null; ODataMediaType expectedMediaType = MyFormat.MediaTypeWithFormatA.MediaType; if (payloadKind == ODataPayloadKind.Batch) { expectedBoundary = "ba_" + Guid.NewGuid(); contentType += ";boundary=" + expectedBoundary; expectedMediaType = new ODataMediaType("text", "x-A", new KeyValuePair <string, string>("boundary", expectedBoundary)); } ODataMediaType mediaType; Encoding encoding; ODataPayloadKind selectedPayloadKind; ODataFormat actual = MediaTypeUtils.GetFormatFromContentType(contentType, new[] { payloadKind }, resolver, out mediaType, out encoding, out selectedPayloadKind); Assert.Equal(MyFormat.Instance, actual); Assert.Equal(expectedMediaType.FullTypeName, mediaType.FullTypeName); Assert.Equal(payloadKind == ODataPayloadKind.BinaryValue ? null : Encoding.UTF8, encoding); Assert.Equal(payloadKind, selectedPayloadKind); } }
/// <summary>Constructor.</summary> /// <param name="format">The format for this input context.</param> /// <param name="reader">The reader to use.</param> /// <param name="contentType">The content type of the message to read.</param> /// <param name="messageReaderSettings">Configuration settings of the OData reader.</param> /// <param name="version">The OData protocol version to be used for reading the payload.</param> /// <param name="readingResponse">true if reading a response message; otherwise false.</param> /// <param name="synchronous">true if the input should be read synchronously; false if it should be read asynchronously.</param> /// <param name="model">The model to use.</param> /// <param name="urlResolver">The optional URL resolver to perform custom URL resolution for URLs read from the payload.</param> /// <param name="payloadKindDetectionState">JSON Ligth specific state stored during payload kind detection (or null if no payload kind detection happened).</param> internal ODataJsonLightInputContext( ODataFormat format, TextReader reader, MediaType contentType, ODataMessageReaderSettings messageReaderSettings, ODataVersion version, bool readingResponse, bool synchronous, IEdmModel model, IODataUrlResolver urlResolver, ODataJsonLightPayloadKindDetectionState payloadKindDetectionState) : base(format, messageReaderSettings, version, readingResponse, synchronous, model, urlResolver) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(reader != null, "reader != null"); Debug.Assert(contentType != null, "contentType != null"); try { ExceptionUtils.CheckArgumentNotNull(format, "format"); ExceptionUtils.CheckArgumentNotNull(messageReaderSettings, "messageReaderSettings"); } catch (ArgumentNullException) { // Dispose the message stream if we failed to create the input context. reader.Dispose(); throw; } try { this.textReader = reader; if (contentType.HasStreamingSetToTrue()) { this.jsonReader = new BufferingJsonReader( this.textReader, ODataAnnotationNames.ODataError, messageReaderSettings.MessageQuotas.MaxNestingDepth, ODataFormat.Json); } else { // If we have a non-streaming Json Light content type we need to use the re-ordering Json reader this.jsonReader = new ReorderingJsonReader(this.textReader, messageReaderSettings.MessageQuotas.MaxNestingDepth); } } catch (Exception e) { // Dispose the message stream if we failed to create the input context. if (ExceptionUtils.IsCatchableExceptionType(e) && reader != null) { reader.Dispose(); } throw; } this.payloadKindDetectionState = payloadKindDetectionState; }
/// <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); } }
/// <summary> /// Asynchronously create ATOM output context. /// </summary> /// <param name="format">The format to create the output context for.</param> /// <param name="message">The message to use.</param> /// <param name="encoding">The encoding to use.</param> /// <param name="messageWriterSettings">Configuration settings of the OData writer.</param> /// <param name="writingResponse">true if writing a response message; otherwise false.</param> /// <param name="model">The model to use.</param> /// <param name="urlResolver">The optional URL resolver to perform custom URL resolution for URLs written to the payload.</param> /// <returns>Task which when completed returns the newly created output context.</returns> internal static Task <ODataOutputContext> CreateAsync( ODataFormat format, ODataMessage message, Encoding encoding, ODataMessageWriterSettings messageWriterSettings, bool writingResponse, IEdmModel model, IODataUrlResolver urlResolver) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(format == ODataFormat.Atom, "This method only supports the ATOM format."); Debug.Assert(message != null, "message != null"); Debug.Assert(messageWriterSettings != null, "messageWriterSettings != null"); return(message.GetStreamAsync() .FollowOnSuccessWith( (streamTask) => (ODataOutputContext) new ODataAtomOutputContext( format, streamTask.Result, encoding, messageWriterSettings, writingResponse, false, model, urlResolver))); }
private static string GetLiteralValue(object value, ODataFormat format, PayloadGeneratorSettings settings) { JsonPayloadGenerator generator; if (format == ODataFormat.Json) { generator = new JsonLightPayloadGenerator(settings); } else { Assert.Fail("Format not supported by UriOperationParameterGenerator."); return(null); } var payloadBuilder = value as PayloadBuilder; if (payloadBuilder != null) { return(generator.GenerateLiteral(payloadBuilder)); } var collectionBuilder = value as CollectionPropertyPayloadBuilder; if (collectionBuilder != null) { return(generator.GenerateLiteral(collectionBuilder)); } // Use the key syntax since that will give us single quotes and other formatting that is not used for literals as property values return(JsonPrimitiveTypesUtil.PrimitiveToKeyString(value, value.GetType())); }
/// <summary> /// Create ATOM output context. /// </summary> /// <param name="format">The format to create the output context for.</param> /// <param name="message">The message to use.</param> /// <param name="encoding">The encoding to use.</param> /// <param name="messageWriterSettings">Configuration settings of the OData writer.</param> /// <param name="writingResponse">true if writing a response message; otherwise false.</param> /// <param name="model">The model to use.</param> /// <param name="urlResolver">The optional URL resolver to perform custom URL resolution for URLs written to the payload.</param> /// <returns>The newly created output context.</returns> internal static ODataOutputContext Create( ODataFormat format, ODataMessage message, Encoding encoding, ODataMessageWriterSettings messageWriterSettings, bool writingResponse, IEdmModel model, IODataUrlResolver urlResolver) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(format == ODataFormat.Atom, "This method only supports the ATOM format."); Debug.Assert(message != null, "message != null"); Debug.Assert(messageWriterSettings != null, "messageWriterSettings != null"); Stream messageStream = message.GetStream(); return(new ODataAtomOutputContext( format, messageStream, encoding, messageWriterSettings, writingResponse, true, model, urlResolver)); }
/// <summary> /// Asynchronously create JSON input context. /// </summary> /// <param name="format">The format for the input context.</param> /// <param name="message">The message to use.</param> /// <param name="encoding">The encoding to use.</param> /// <param name="messageReaderSettings">Configuration settings of the OData reader.</param> /// <param name="version">The OData protocol version to be used for reading the payload.</param> /// <param name="readingResponse">true if reading a response message; otherwise false.</param> /// <param name="model">The model to use.</param> /// <param name="urlResolver">The optional URL resolver to perform custom URL resolution for URLs read from the payload.</param> /// <returns>Task which when completed returns the newly created input context.</returns> internal static Task <ODataInputContext> CreateAsync( ODataFormat format, ODataMessage message, Encoding encoding, ODataMessageReaderSettings messageReaderSettings, ODataVersion version, bool readingResponse, IEdmModel model, IODataUrlResolver urlResolver) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(message != null, "message != null"); Debug.Assert(messageReaderSettings != null, "messageReaderSettings != null"); return(message.GetStreamAsync() .FollowOnSuccessWith( (streamTask) => (ODataInputContext) new ODataJsonInputContext( format, streamTask.Result, encoding, messageReaderSettings, version, readingResponse, false, model, urlResolver))); }
/// <summary>Constructor.</summary> /// <param name="format">The format for this input context.</param> /// <param name="reader">The reader to read data from.</param> /// <param name="messageReaderSettings">Configuration settings of the OData reader.</param> /// <param name="version">The OData protocol version to be used for reading the payload.</param> /// <param name="readingResponse">true if reading a response message; otherwise false.</param> /// <param name="synchronous">true if the input should be read synchronously; false if it should be read asynchronously.</param> /// <param name="model">The model to use.</param> /// <param name="urlResolver">The optional URL resolver to perform custom URL resolution for URLs read from the payload.</param> internal ODataJsonInputContext( ODataFormat format, TextReader reader, ODataMessageReaderSettings messageReaderSettings, ODataVersion version, bool readingResponse, bool synchronous, IEdmModel model, IODataUrlResolver urlResolver) : base(format, messageReaderSettings, version, readingResponse, synchronous, model, urlResolver) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(reader != null, "reader != null"); ExceptionUtils.CheckArgumentNotNull(format, "format"); ExceptionUtils.CheckArgumentNotNull(messageReaderSettings, "messageReaderSettings"); try { this.textReader = reader; this.jsonReader = new BufferingJsonReader(this.textReader, /*removeDuplicateProperties*/ this.UseServerFormatBehavior, messageReaderSettings.MessageQuotas.MaxNestingDepth); } catch (Exception e) { // Dispose the message stream if we failed to create the input context. if (ExceptionUtils.IsCatchableExceptionType(e) && reader != null) { reader.Dispose(); } throw; } }
/// <summary> /// Create JSON input context. /// </summary> /// <param name="format">The format for the input context.</param> /// <param name="message">The message to use.</param> /// <param name="encoding">The encoding to use.</param> /// <param name="messageReaderSettings">Configuration settings of the OData reader.</param> /// <param name="version">The OData protocol version to be used for reading the payload.</param> /// <param name="readingResponse">true if reading a response message; otherwise false.</param> /// <param name="model">The model to use.</param> /// <param name="urlResolver">The optional URL resolver to perform custom URL resolution for URLs read from the payload.</param> /// <returns>The newly created input context.</returns> internal static ODataInputContext Create( ODataFormat format, ODataMessage message, Encoding encoding, ODataMessageReaderSettings messageReaderSettings, ODataVersion version, bool readingResponse, IEdmModel model, IODataUrlResolver urlResolver) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(message != null, "message != null"); Debug.Assert(messageReaderSettings != null, "messageReaderSettings != null"); Stream messageStream = message.GetStream(); return(new ODataJsonInputContext( format, messageStream, encoding, messageReaderSettings, version, readingResponse, true, model, urlResolver)); }
/// <summary> /// Constructor. /// </summary> /// <param name="format">The format used for the test.</param> /// <param name="version">The OData protocol version to be used for the payload.</param> /// <param name="request">True if the test is reading a request. Otherwise false if it's reading a response.</param> public TestConfiguration(ODataFormat format, ODataVersion version, bool request, TestODataBehaviorKind behaviorKind) { this.Format = format; this.Version = version; this.IsRequest = request; this.RunBehaviorKind = behaviorKind; }
private ODataJsonOutputContext(ODataFormat format, Stream messageStream, Encoding encoding, ODataMessageWriterSettings messageWriterSettings, bool writingResponse, bool synchronous, IEdmModel model, IODataUrlResolver urlResolver) : base(format, messageWriterSettings, writingResponse, synchronous, model, urlResolver) { try { Stream asynchronousOutputStream; this.messageOutputStream = messageStream; if (synchronous) { asynchronousOutputStream = messageStream; } else { this.asynchronousOutputStream = new AsyncBufferedStream(messageStream); asynchronousOutputStream = this.asynchronousOutputStream; } this.textWriter = new StreamWriter(asynchronousOutputStream, encoding); this.jsonWriter = new Microsoft.Data.OData.Json.JsonWriter(this.textWriter, messageWriterSettings.Indent); } catch (Exception exception) { if (ExceptionUtils.IsCatchableExceptionType(exception) && (messageStream != null)) { messageStream.Dispose(); } throw; } }
private void WriteAnnotationAtStartExpandedFeedShouldFail(ODataFormat format) { Action <ODataWriter> action = (odataWriter) => { var entryToWrite = new ODataResource { Properties = new[] { new ODataProperty { Name = "ID", Value = 1 } } }; odataWriter.WriteStart(entryToWrite); ODataNestedResourceInfo navLink = new ODataNestedResourceInfo { Name = "ResourceSetNavigationProperty", IsCollection = true }; odataWriter.WriteStart(navLink); var feedToWrite = new ODataResourceSet { Id = new Uri("urn:feedId") }; feedToWrite.InstanceAnnotations.Add(new ODataInstanceAnnotation("custom.StartFeedAnnotation", PrimitiveValue1)); odataWriter.WriteStart(feedToWrite); }; Action testResponse = () => this.WriteAnnotationsAndValidatePayload(action, EntitySet, format, null, request: false, createFeedWriter: false); testResponse.ShouldThrow <ODataException>().WithMessage(Strings.ODataJsonLightWriter_InstanceAnnotationNotSupportedOnExpandedResourceSet); Action testRequest = () => this.WriteAnnotationsAndValidatePayload(action, EntitySet, format, null, request: true, createFeedWriter: false); testRequest.ShouldThrow <ODataException>().WithMessage(Strings.ODataJsonLightWriter_InstanceAnnotationNotSupportedOnExpandedResourceSet); }
public void ContentTypeHeaderParsingErrorTest() { var testCases = new ContentTypeTestCase[] { new ContentTypeTestCase { ContentType = null, ExpectedException = ODataExpectedExceptions.ODataContentTypeException("ODataMessageReader_NoneOrEmptyContentTypeHeader") }, new ContentTypeTestCase { ContentType = string.Empty, ExpectedException = ODataExpectedExceptions.ODataContentTypeException("ODataMessageReader_NoneOrEmptyContentTypeHeader") }, new ContentTypeTestCase { ContentType = ";foo=bar", ExpectedException = ODataExpectedExceptions.ODataContentTypeException("HttpUtils_MediaTypeRequiresSlash", ";foo=bar") }, new ContentTypeTestCase { ContentType = "application/*", ExpectedException = ODataExpectedExceptions.ODataContentTypeException("ODataMessageReader_WildcardInContentType", "application/*") }, new ContentTypeTestCase { ContentType = "*/*", ExpectedException = ODataExpectedExceptions.ODataContentTypeException("ODataMessageReader_WildcardInContentType", "*/*") }, new ContentTypeTestCase { ContentType = "application/json, application/xml", ExpectedException = ODataExpectedExceptions.ODataContentTypeException("MediaTypeUtils_NoOrMoreThanOneContentTypeSpecified", "application/json, application/xml") }, }; this.CombinatorialEngineProvider.RunCombinations( testCases, this.ReaderTestConfigurationProvider.AllFormatConfigurations.Where(tc => tc.Format != ODataFormat.Json), (testCase, testConfiguration) => { // create a message reader and call GetFormat; this should fail with the expected error message TestMessage testMessage = TestReaderUtils.CreateInputMessageFromStream(new TestStream(), testConfiguration); testMessage.SetHeader(Microsoft.OData.Core.ODataConstants.ContentTypeHeader, testCase.ContentType); testMessage.SetHeader(Microsoft.OData.Core.ODataConstants.ContentLengthHeader, testCase.ContentLength.ToString()); TestExceptionUtils.ExpectedException( this.Assert, () => { using (ODataMessageReaderTestWrapper messageReader = TestReaderUtils.CreateMessageReader(testMessage, null, testConfiguration)) { ODataFormat actualFormat = messageReader.DetectPayloadKind().Single().Format; } }, testCase.ExpectedException, this.ExceptionVerifier); }); }
/// <summary> /// Sets the acceptable media types and character sets from which the content type will be computed when writing the payload. /// </summary> /// <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> /// <remarks>Calling this method replaces any previously set content-type settings.</remarks> public void SetContentType(string acceptableMediaTypes, string acceptableCharSets) { ExceptionUtils.CheckArgumentNotNull(acceptableMediaTypes, "acceptableMediaTypes"); this.acceptMediaTypes = acceptableMediaTypes; this.acceptCharSets = acceptableCharSets; this.format = ODataFormat.Default; }
/// <summary> /// Creates a new instance of Json writer. /// </summary> /// <param name="writer">Writer to which text needs to be written.</param> /// <param name="indent">If the output should be indented or not.</param> /// <param name="jsonFormat">The json-based format to use when writing.</param> internal JsonWriter(TextWriter writer, bool indent, ODataFormat jsonFormat) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(jsonFormat == ODataFormat.Json || jsonFormat == ODataFormat.VerboseJson, "Expected a json-based format."); this.writer = new IndentedTextWriter(writer, indent); this.scopes = new Stack <Scope>(); this.mustWriteDecimalPointInDoubleValues = jsonFormat == ODataFormat.Json; }
/// <summary> /// Constructor. /// </summary> /// <param name="format">The format used for the test.</param> /// <param name="messageReaderSettings">The message reader settings used for the test.</param> /// <param name="readerRequest">True if the test is reading a request. Otherwise false if it's reading a response.</param> /// <param name="synchronous">True if the test should be ran using synchronous API. Otherwise false if it should be ran using asynchronous APIs.</param> /// <param name="version">The OData protocol version to be used for reading the payload.</param> public ReaderTestConfiguration(ODataFormat format, ODataMessageReaderSettings messageReaderSettings, bool IsRequest, bool synchronous, ODataVersion version = ODataVersion.V4) : base(format, version, IsRequest, TestODataBehaviorKind.Default) { Debug.Assert(messageReaderSettings != null, "readerSettings != null"); this.MessageReaderSettings = messageReaderSettings; this.Synchronous = synchronous; }
/// <summary> /// Constructor. /// </summary> /// <param name="format">The format for this output context.</param> /// <param name="messageStream">The message stream to write the payload to.</param> /// <param name="mediaType">The specific media type being written.</param> /// <param name="encoding">The encoding to use for the payload.</param> /// <param name="messageWriterSettings">Configuration settings of the OData writer.</param> /// <param name="writingResponse">true if writing a response message; otherwise false.</param> /// <param name="synchronous">true if the output should be written synchronously; false if it should be written asynchronously.</param> /// <param name="model">The model to use.</param> /// <param name="urlResolver">The optional URL resolver to perform custom URL resolution for URLs written to the payload.</param> internal ODataJsonLightOutputContext(ODataFormat format, Stream messageStream, ODataMediaType mediaType, Encoding encoding, ODataMessageWriterSettings messageWriterSettings, bool writingResponse, bool synchronous, IEdmModel model, IODataUrlResolver urlResolver) : base(format, messageStream, encoding, messageWriterSettings, writingResponse, synchronous, mediaType.HasIeee754CompatibleSetToTrue(), model, urlResolver) { Debug.Assert(messageStream != null, "messageStream != null"); Debug.Assert(messageWriterSettings != null, "messageWriterSettings != null"); Debug.Assert(mediaType != null, "mediaType != null"); Uri metadataDocumentUri = messageWriterSettings.MetadataDocumentUri; this.metadataLevel = JsonLightMetadataLevel.Create(mediaType, metadataDocumentUri, model, writingResponse); }
/// <summary> /// Constructor. /// </summary> /// <param name="reader">The text reader to read input characters from.</param> /// <param name="inStreamErrorPropertyName">The name of the property that denotes an in-stream error.</param> /// <param name="maxInnerErrorDepth">The maximum number of recursive internalexception objects to allow when reading in-stream errors.</param> /// <param name="jsonFormat">The specific JSON-based format expected by the reader.</param> /// <param name="isIeee754Compatible">If it is IEEE754 Compatible</param> internal BufferingJsonReader(TextReader reader, string inStreamErrorPropertyName, int maxInnerErrorDepth, ODataFormat jsonFormat, bool isIeee754Compatible) : base(reader, jsonFormat, isIeee754Compatible) { Debug.Assert(reader != null, "reader != null"); this.inStreamErrorPropertyName = inStreamErrorPropertyName; this.maxInnerErrorDepth = maxInnerErrorDepth; this.bufferedNodesHead = null; this.currentBufferedNode = null; }
/// <summary> /// Constructor. /// </summary> /// <param name="format">The format for this output context.</param> /// <param name="jsonWriter">The JSON writer to write to.</param> /// <param name="messageWriterSettings">Configuration settings of the OData writer.</param> /// <param name="writingResponse">true if writing a response message; otherwise false.</param> /// <param name="synchronous">true if the output should be written synchronously; false if it should be written asynchronously.</param> /// <param name="model">The model to use.</param> /// <param name="urlResolver">The optional URL resolver to perform custom URL resolution for URLs written to the payload.</param> private ODataJsonOutputContext( ODataFormat format, JsonWriter jsonWriter, ODataMessageWriterSettings messageWriterSettings, bool writingResponse, bool synchronous, IEdmModel model, IODataUrlResolver urlResolver) : base(format, messageWriterSettings, writingResponse, synchronous, model, urlResolver) { this.jsonWriter = jsonWriter; }
/// <summary> /// Constructor. /// </summary> /// <param name="format">The format for this output context.</param> /// <param name="textWriter">The text writer to write to.</param> /// <param name="messageWriterSettings">Configuration settings of the OData writer.</param> /// <param name="model">The model to use.</param> protected internal ODataJsonOutputContextBase( ODataFormat format, TextWriter textWriter, ODataMessageWriterSettings messageWriterSettings, IEdmModel model) : base(format, messageWriterSettings, false /*writingResponse*/, true /*synchronous*/, model, null /*urlResolver*/) { Debug.Assert(textWriter != null, "textWriter != null"); this.textWriter = textWriter; this.jsonWriter = new JsonWriter(this.textWriter, messageWriterSettings.Indent, format, true /*isIeee754Compatible*/); }
/// <summary> /// Constructor. /// </summary> /// <param name="format">The format for this output context.</param> /// <param name="textWriter">The text writer to write to.</param> /// <param name="messageWriterSettings">Configuration settings of the OData writer.</param> /// <param name="model">The model to use.</param> internal ODataJsonLightOutputContext( ODataFormat format, TextWriter textWriter, ODataMessageWriterSettings messageWriterSettings, IEdmModel model) : base(format, textWriter, messageWriterSettings, model) { Debug.Assert(!this.WritingResponse, "Expecting WritingResponse to always be false for this constructor, so no need to validate the MetadataDocumentUri on the writer settings."); Debug.Assert(textWriter != null, "textWriter != null"); Debug.Assert(messageWriterSettings != null, "messageWriterSettings != null"); this.metadataLevel = new JsonMinimalMetadataLevel(); }
/// <summary>Constructor.</summary> /// <param name="format">The format for this input context.</param> /// <param name="messageStream">The stream to read data from.</param> /// <param name="contentType">The content type of the message to read.</param> /// <param name="encoding">The encoding to use to read the input.</param> /// <param name="messageReaderSettings">Configuration settings of the OData reader.</param> /// <param name="readingResponse">true if reading a response message; otherwise false.</param> /// <param name="synchronous">true if the input should be read synchronously; false if it should be read asynchronously.</param> /// <param name="model">The model to use.</param> /// <param name="urlResolver">The optional URL resolver to perform custom URL resolution for URLs read from the payload.</param> internal ODataJsonLightInputContext( ODataFormat format, Stream messageStream, ODataMediaType contentType, Encoding encoding, ODataMessageReaderSettings messageReaderSettings, bool readingResponse, bool synchronous, IEdmModel model, IODataUrlResolver urlResolver) : this(format, CreateTextReaderForMessageStreamConstructor(messageStream, encoding), contentType, messageReaderSettings, readingResponse, synchronous, model, urlResolver) { }
/// <summary> /// Creates a new instance of Json writer. /// </summary> /// <param name="writer">Writer to which text needs to be written.</param> /// <param name="indent">If the output should be indented or not.</param> /// <param name="jsonFormat">The json-based format to use when writing.</param> /// <param name="isIeee754Compatible">if it is IEEE754Compatible</param> internal JsonWriter(TextWriter writer, bool indent, ODataFormat jsonFormat, bool isIeee754Compatible) { Debug.Assert(jsonFormat == ODataFormat.Json, "Expected a json-based format."); if (indent == true) { this.writer = new IndentedTextWriter(writer); } else { this.writer = new NonIndentedTextWriter(writer); } this.scopes = new Stack<Scope>(); this.isIeee754Compatible = isIeee754Compatible; }
protected internal ODataJsonOutputContextBase( ODataFormat format, Stream messageStream, Encoding encoding, ODataMessageWriterSettings messageWriterSettings, bool writingResponse, bool synchronous, bool isIeee754Compatible, IEdmModel model, IODataUrlResolver urlResolver) : base(format, messageWriterSettings, writingResponse, synchronous, model, urlResolver) { Debug.Assert(messageStream != null, "messageStream != null"); try { this.messageOutputStream = messageStream; Stream outputStream; if (synchronous) { outputStream = messageStream; } else { this.asynchronousOutputStream = new AsyncBufferedStream(messageStream); outputStream = this.asynchronousOutputStream; } this.textWriter = new StreamWriter(outputStream, encoding); // COMPAT 2: JSON indentation - WCFDS indents only partially, it inserts newlines but doesn't actually insert spaces for indentation // in here we allow the user to specify if true indentation should be used or if the limited functionality is enough. this.jsonWriter = new JsonWriter(this.textWriter, messageWriterSettings.Indent, format, isIeee754Compatible); } catch (Exception e) { // Dispose the message stream if we failed to create the input context. if (ExceptionUtils.IsCatchableExceptionType(e) && messageStream != null) { messageStream.Dispose(); } throw; } }
/// <summary> /// Constructor. /// </summary> /// <param name="format">The format for this output context.</param> /// <param name="messageStream">The message stream to write the payload to.</param> /// <param name="encoding">The encoding to use for the payload.</param> /// <param name="messageWriterSettings">Configuration settings of the OData writer.</param> /// <param name="writingResponse">true if writing a response message; otherwise false.</param> /// <param name="synchronous">true if the output should be written synchronously; false if it should be written asynchronously.</param> /// <param name="model">The model to use.</param> /// <param name="urlResolver">The optional URL resolver to perform custom URL resolution for URLs written to the payload.</param> private ODataAtomOutputContext( ODataFormat format, Stream messageStream, Encoding encoding, ODataMessageWriterSettings messageWriterSettings, bool writingResponse, bool synchronous, IEdmModel model, IODataUrlResolver urlResolver) : base(format, messageWriterSettings, writingResponse, synchronous, model, urlResolver) { Debug.Assert(messageStream != null, "stream != null"); try { this.messageOutputStream = messageStream; Stream outputStream; if (synchronous) { outputStream = messageStream; } else { this.asynchronousOutputStream = new AsyncBufferedStream(messageStream); outputStream = this.asynchronousOutputStream; } this.xmlRootWriter = ODataAtomWriterUtils.CreateXmlWriter(outputStream, messageWriterSettings, encoding); this.xmlWriter = this.xmlRootWriter; } catch (Exception e) { // Dispose the message stream if we failed to create the input context. if (ExceptionUtils.IsCatchableExceptionType(e) && messageStream != null) { messageStream.Dispose(); } throw; } }
/// <summary> /// Constructor. /// </summary> /// <param name="format">The format for this output context.</param> /// <param name="messageStream">The message stream to write the payload to.</param> /// <param name="encoding">The encoding to use for the payload.</param> /// <param name="messageWriterSettings">Configuration settings of the OData writer.</param> /// <param name="writingResponse">true if writing a response message; otherwise false.</param> /// <param name="synchronous">true if the output should be written synchronously; false if it should be written asynchronously.</param> /// <param name="model">The model to use.</param> /// <param name="urlResolver">The optional URL resolver to perform custom URL resolution for URLs written to the payload.</param> private ODataJsonOutputContext( ODataFormat format, Stream messageStream, Encoding encoding, ODataMessageWriterSettings messageWriterSettings, bool writingResponse, bool synchronous, IEdmModel model, IODataUrlResolver urlResolver) : base(format, messageWriterSettings, writingResponse, synchronous, model, urlResolver) { try { this.messageOutputStream = messageStream; Stream outputStream; if (synchronous) { outputStream = messageStream; } else { this.asynchronousOutputStream = new AsyncBufferedStream(messageStream); outputStream = this.asynchronousOutputStream; } this.textWriter = new StreamWriter(outputStream, encoding); this.jsonWriter = new JsonWriter(this.textWriter, messageWriterSettings.Indent); } catch (Exception e) { // Dispose the message stream if we failed to create the input context. if (ExceptionUtils.IsCatchableExceptionType(e) && messageStream != null) { messageStream.Dispose(); } throw; } }
internal ODataAtomInputContext( ODataFormat format, Stream messageStream, Encoding encoding, ODataMessageReaderSettings messageReaderSettings, bool readingResponse, bool synchronous, IEdmModel model, IODataUrlResolver urlResolver) : base(format, messageReaderSettings, readingResponse, synchronous, model, urlResolver) { Debug.Assert(messageStream != null, "stream != null"); try { ExceptionUtils.CheckArgumentNotNull(format, "format"); ExceptionUtils.CheckArgumentNotNull(messageReaderSettings, "messageReaderSettings"); // Which encoding do we use when reading XML payloads this.baseXmlReader = ODataAtomReaderUtils.CreateXmlReader(messageStream, encoding, messageReaderSettings); // For WCF DS Server behavior we need to turn off xml:base processing for V1/V2 back compat. this.xmlReader = new BufferingXmlReader( this.baseXmlReader, /*parentXmlReader*/ null, messageReaderSettings.BaseUri, /*disableXmlBase*/ false, messageReaderSettings.MessageQuotas.MaxNestingDepth); } catch (Exception e) { // Dispose the message stream if we failed to create the input context. if (ExceptionUtils.IsCatchableExceptionType(e) && messageStream != null) { messageStream.Dispose(); } throw; } }
protected void WriteAnnotationsAndValidatePayload(Action<ODataWriter> action, ODataFormat format, string expectedPayload, bool request, bool createFeedWriter) { var writerSettings = new ODataMessageWriterSettings { DisableMessageStreamDisposal = true, EnableAtom = true }; writerSettings.SetContentType(format); writerSettings.SetServiceDocumentUri(new Uri("http://www.example.com/")); MemoryStream stream = new MemoryStream(); if (request) { IODataRequestMessage requestMessageToWrite = new InMemoryMessage { Method = "GET", Stream = stream }; using (var messageWriter = new ODataMessageWriter(requestMessageToWrite, writerSettings, Model)) { ODataWriter odataWriter = createFeedWriter ? messageWriter.CreateODataFeedWriter(EntitySet, EntityType) : messageWriter.CreateODataEntryWriter(EntitySet, EntityType); action(odataWriter); } } else { IODataResponseMessage responseMessageToWrite = new InMemoryMessage { StatusCode = 200, Stream = stream }; using (var messageWriter = new ODataMessageWriter(responseMessageToWrite, writerSettings, Model)) { ODataWriter odataWriter = createFeedWriter ? messageWriter.CreateODataFeedWriter(EntitySet, EntityType) : messageWriter.CreateODataEntryWriter(EntitySet, EntityType); action(odataWriter); } } stream.Position = 0; string payload = (new StreamReader(stream)).ReadToEnd(); if (format == ODataFormat.Atom) { // The <updated> element is computed dynamically, so we remove it from the both the baseline and the actual payload. payload = Regex.Replace(payload, "<updated>[^<]*</updated>", ""); expectedPayload = Regex.Replace(expectedPayload, "<updated>[^<]*</updated>", ""); } Assert.Equal(expectedPayload, payload); }
/// <summary> /// Constructor. /// </summary> /// <param name="reader">The text reader to read input characters from.</param> /// <param name="jsonFormat">The specific JSON-based format expected by the reader.</param> /// <param name="isIeee754Compatible">If it is isIeee754Compatible</param> public JsonReader(TextReader reader, ODataFormat jsonFormat, bool isIeee754Compatible) { Debug.Assert(reader != null, "reader != null"); Debug.Assert(jsonFormat == ODataFormat.Json, "Expected a json-based format to create a JsonReader"); this.nodeType = JsonNodeType.None; this.nodeValue = null; this.reader = reader; this.characterBuffer = new char[InitialCharacterBufferSize]; this.storedCharacterCount = 0; this.tokenStartIndex = 0; this.endOfInputReached = false; this.isIeee754Compatible = isIeee754Compatible; this.allowAnnotations = jsonFormat == ODataFormat.Json; this.scopes = new Stack<Scope>(); this.scopes.Push(new Scope(ScopeType.Root)); }
/// <summary> /// Sets the format to be used when writing the payload. This will automatically set a compatible /// content type header. /// </summary> /// <param name="payloadFormat">The format to use for writing the payload.</param> /// <remarks>Calling this method replaces any previously set content-type settings.</remarks> public void SetContentType(ODataFormat payloadFormat) { this.acceptCharSets = null; this.acceptMediaTypes = null; this.format = payloadFormat; }
/// <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 (or writer creation) methods on the <see cref="ODataMessageWriter"/>. /// If it is sufficient to set the headers when the write (or writer creation) methods on the <see cref="ODataMessageWriter"/> /// 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 this message writer.</param> internal void SetHeaders(ODataPayloadKind payloadKind) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(payloadKind != ODataPayloadKind.Unsupported, "payloadKind != ODataPayloadKind.Unsupported"); this.writerPayloadKind = payloadKind; // Determine the content type and format from the settings. MediaType mediaType; this.format = MediaTypeUtils.GetContentTypeFromSettings(this.settings, payloadKind, out mediaType, out this.encoding); string contentType; if (payloadKind == ODataPayloadKind.Batch) { // Note that this serves as verification only for now, since we only support a single content type and format for $batch payloads. Debug.Assert(this.format == ODataFormat.Default, "$batch should only support default format since it's format independent."); Debug.Assert(mediaType.TypeName == MimeConstants.MimeMultipartMixed, "$batch content type is currently only supported to be multipart/mixed."); //// TODO: Bug 135611: What about the encoding - should we verify that it's 7bit US-ASCII only? this.batchBoundary = ODataBatchWriterUtils.CreateBatchBoundary(this.writingResponse); // Set the content type header here since all headers have to be set before getting the stream // Note that the mediaType may have additional parameters, which we ignore here (intentional as per MIME spec). // Note that we always generate a new boundary string here, even if the accept header contained one. // We need the boundary to be as unique as possible to avoid possible collision with content of the batch operation payload. // Our boundary string are generated to fulfill this requirement, client specified ones might not which might lead to wrong responses // and at least in theory security issues. contentType = ODataBatchWriterUtils.CreateMultipartMixedContentType(this.batchBoundary); } else { this.batchBoundary = null; // compute the content type (incl. charset) and set the Content-Type header on the response message contentType = HttpUtils.BuildContentType(mediaType, this.encoding); } this.message.SetHeader(ODataHttpHeaders.ContentType, contentType); // Set the data service version ODataUtilsInternal.SetDataServiceVersion(this.message, this.settings); }
internal ODataJsonLightInputContext( ODataFormat format, TextReader reader, ODataMediaType contentType, ODataMessageReaderSettings messageReaderSettings, bool readingResponse, bool synchronous, IEdmModel model, IODataUrlResolver urlResolver) : base(format, messageReaderSettings, readingResponse, synchronous, model, urlResolver) { Debug.Assert(reader != null, "reader != null"); Debug.Assert(contentType != null, "contentType != null"); try { ExceptionUtils.CheckArgumentNotNull(format, "format"); ExceptionUtils.CheckArgumentNotNull(messageReaderSettings, "messageReaderSettings"); } catch (ArgumentNullException) { // Dispose the message stream if we failed to create the input context. reader.Dispose(); throw; } try { this.textReader = reader; if (contentType.HasStreamingSetToTrue()) { this.jsonReader = new BufferingJsonReader( this.textReader, JsonLightConstants.ODataErrorPropertyName, messageReaderSettings.MessageQuotas.MaxNestingDepth, ODataFormat.Json, contentType.HasIeee754CompatibleSetToTrue()); } else { // If we have a non-streaming Json Light content type we need to use the re-ordering Json reader this.jsonReader = new ReorderingJsonReader(this.textReader, messageReaderSettings.MessageQuotas.MaxNestingDepth, contentType.HasIeee754CompatibleSetToTrue()); } } catch (Exception e) { // Dispose the message stream if we failed to create the input context. if (ExceptionUtils.IsCatchableExceptionType(e) && reader != null) { reader.Dispose(); } throw; } // dont know how to get MetadataDocumentUri uri here, messageReaderSettings do not have one // Uri metadataDocumentUri = messageReaderSettings..MetadataDocumentUri == null ? null : messageReaderSettings.MetadataDocumentUri.BaseUri; // the uri here is used here to create the FullMetadataLevel can pass null in this.metadataLevel = JsonLight.JsonLightMetadataLevel.Create(contentType, null, model, readingResponse); }
public AndConstraint<MediaTypeAssertions> HaveExactFormat(ODataFormat format) { this.Format.Should().BeSameAs(format); return new AndConstraint<MediaTypeAssertions>(this); }
private void WriteAnnotationOnExpandedEntriesNotInExpandedFeed(IEdmNavigationSource navigationSource, ODataFormat format, string expectedPayload) { Action<ODataWriter> action = (odataWriter) => { var entryToWrite = new ODataEntry {Properties = new[] {new ODataProperty {Name = "ID", Value = 1}}}; odataWriter.WriteStart(entryToWrite); ODataNavigationLink navLink = new ODataNavigationLink {Name = "ResourceNavigationProperty", IsCollection = false}; if (format == ODataFormat.Atom) { navLink.Url = new Uri("http://service/navLink", UriKind.RelativeOrAbsolute); } odataWriter.WriteStart(navLink); entryToWrite = new ODataEntry {Properties = new[] {new ODataProperty {Name = "ID", Value = 1}}}; entryToWrite.InstanceAnnotations.Add(new ODataInstanceAnnotation("Custom.StartAnnotation", PrimitiveValue1)); odataWriter.WriteStart(entryToWrite); entryToWrite.EditLink = tempUri; entryToWrite.InstanceAnnotations.Add(new ODataInstanceAnnotation("Custom.EndAnnotation", PrimitiveValue1)); odataWriter.WriteEnd(); odataWriter.WriteEnd(); odataWriter.WriteEnd(); }; this.WriteAnnotationsAndValidatePayload(action, navigationSource, format, expectedPayload, request: false, createFeedWriter: false); this.WriteAnnotationsAndValidatePayload(action, navigationSource, format, expectedPayload, request: true, createFeedWriter: false); }
private void WriteAnnotationAtEndOnTopLevelFeed(string expectedPayload, ODataFormat format, long? count, Uri nextLink, bool request) { Action<ODataWriter> action = (odataWriter) => { var feedToWrite = new ODataFeed { Id = new Uri("urn:feedId") }; odataWriter.WriteStart(feedToWrite); feedToWrite.InstanceAnnotations.Add(new ODataInstanceAnnotation("Custom.EndAnnotation", PrimitiveValue1)); feedToWrite.Count = count; feedToWrite.NextPageLink = nextLink; odataWriter.WriteEnd(); }; WriteAnnotationsAndValidatePayload(action, EntitySet, format, expectedPayload, request, createFeedWriter: true); }
internal static TestMediaTypeWithFormat GetResponseTypeFromFormat(ODataFormat format, ODataVersion version) { return GetResponseType(version, s => s.SetContentType(format)); }
private void WriteAnnotationAtStartOnTopLevelEntry(IEdmNavigationSource navigationSource, ODataFormat format, string expectedPayload) { Action<ODataWriter> action = (odataWriter) => { var entryToWrite = new ODataEntry {Properties = new[] {new ODataProperty {Name = "ID", Value = 1}}}; entryToWrite.InstanceAnnotations.Add(new ODataInstanceAnnotation("Custom.PrimitiveCollectionAnnotation", PrimitiveCollectionValue)); odataWriter.WriteStart(entryToWrite); var editLinkUri = tempUri; entryToWrite.EditLink = editLinkUri; odataWriter.WriteEnd(); }; this.WriteAnnotationsAndValidatePayload(action, navigationSource, format, expectedPayload, request: false, createFeedWriter: false); this.WriteAnnotationsAndValidatePayload(action, navigationSource, format, expectedPayload, request: true, createFeedWriter: false); }
public static FormatQueryPart Format(ODataFormat format) { return new FormatQueryPart(format); }
public TestODataOutputContext(ODataFormat format, ODataMessageWriterSettings messageWriterSettings, bool writingResponse, bool synchronous, IEdmModel model, IODataUrlResolver urlResolver) :base(format, messageWriterSettings, writingResponse, synchronous, model, urlResolver) { }
/// <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; }
/// <summary> /// Create JSON output context. /// </summary> /// <param name="format">The format to create the output context for.</param> /// <param name="jsonWriter">The JSON writer to write to.</param> /// <param name="messageWriterSettings">Configuration settings of the OData writer.</param> /// <param name="writingResponse">true if writing a response message; otherwise false.</param> /// <param name="model">The model to use.</param> /// <param name="urlResolver">The optional URL resolver to perform custom URL resolution for URLs written to the payload.</param> /// <returns>The newly created output context.</returns> /// <remarks>This method is for writing the output directly to the JSON writer, when created with this method /// the output context doesn't support most of the methods on it. Note that Dispose will do nothing in this case.</remarks> internal static ODataJsonOutputContext Create( ODataFormat format, JsonWriter jsonWriter, ODataMessageWriterSettings messageWriterSettings, bool writingResponse, IEdmModel model, IODataUrlResolver urlResolver) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(format == ODataFormat.VerboseJson, "This method only supports the verbose JSON format."); Debug.Assert(jsonWriter != null, "jsonWriter != null"); Debug.Assert(messageWriterSettings != null, "messageWriterSettings != null"); return new ODataJsonOutputContext( format, jsonWriter, messageWriterSettings, writingResponse, true, model, urlResolver); }
/// <summary> /// Create ATOM output context. /// </summary> /// <param name="format">The format to create the output context for.</param> /// <param name="message">The message to use.</param> /// <param name="encoding">The encoding to use.</param> /// <param name="messageWriterSettings">Configuration settings of the OData writer.</param> /// <param name="writingResponse">true if writing a response message; otherwise false.</param> /// <param name="model">The model to use.</param> /// <param name="urlResolver">The optional URL resolver to perform custom URL resolution for URLs written to the payload.</param> /// <returns>The newly created output context.</returns> internal static ODataOutputContext Create( ODataFormat format, ODataMessage message, Encoding encoding, ODataMessageWriterSettings messageWriterSettings, bool writingResponse, IEdmModel model, IODataUrlResolver urlResolver) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(format == ODataFormat.Atom, "This method only supports the ATOM format."); Debug.Assert(message != null, "message != null"); Debug.Assert(messageWriterSettings != null, "messageWriterSettings != null"); Stream messageStream = message.GetStream(); return new ODataAtomOutputContext( format, messageStream, encoding, messageWriterSettings, writingResponse, true, model, urlResolver); }
private void WriteAnnotationAtEndExpandedFeedShouldFail(ODataFormat format) { Action<ODataWriter> action = (odataWriter) => { var entryToWrite = new ODataEntry {Properties = new[] {new ODataProperty {Name = "ID", Value = 1}}}; odataWriter.WriteStart(entryToWrite); ODataNavigationLink navLink = new ODataNavigationLink {Name = "ResourceSetNavigationProperty", Url = new Uri("http://service/navLink", UriKind.RelativeOrAbsolute), IsCollection = true}; odataWriter.WriteStart(navLink); var feedToWrite = new ODataFeed { Id = new Uri("urn:feedId") }; odataWriter.WriteStart(feedToWrite); feedToWrite.InstanceAnnotations.Add(new ODataInstanceAnnotation("custom.StartFeedAnnotation", PrimitiveValue1)); odataWriter.WriteEnd(); }; Action testResponse = () => this.WriteAnnotationsAndValidatePayload(action, EntitySet, format, null, request: false, createFeedWriter: false); testResponse.ShouldThrow<ODataException>().WithMessage(Strings.ODataJsonLightWriter_InstanceAnnotationNotSupportedOnExpandedFeed); Action testResponseOfSingleton = () => this.WriteAnnotationsAndValidatePayload(action, Singleton, format, null, request: false, createFeedWriter: false); testResponseOfSingleton.ShouldThrow<ODataException>().WithMessage(Strings.ODataJsonLightWriter_InstanceAnnotationNotSupportedOnExpandedFeed); Action testRequest = () => this.WriteAnnotationsAndValidatePayload(action, EntitySet, format, null, request: true, createFeedWriter: false); testRequest.ShouldThrow<ODataException>().WithMessage(Strings.ODataJsonLightWriter_InstanceAnnotationNotSupportedOnExpandedFeed); Action testRequestOfSingleton = () => this.WriteAnnotationsAndValidatePayload(action, Singleton, format, null, request: true, createFeedWriter: false); testRequestOfSingleton.ShouldThrow<ODataException>().WithMessage(Strings.ODataJsonLightWriter_InstanceAnnotationNotSupportedOnExpandedFeed); }
private static TestODataWriterCore CreateODataWriterCore(ODataFormat format, bool writingResponse, IEdmModel model, IEdmEntitySet writerSet, IEdmEntityType writerEntityType, bool writeFeed) { var resolver = new TestUrlResolver(); var settings = new ODataMessageWriterSettings { DisableMessageStreamDisposal = true, Version = ODataVersion.V4 }; settings.SetServiceDocumentUri(new Uri("http://example.com")); var outputContext = new TestODataOutputContext(format, settings, writingResponse, false, model, resolver); return new TestODataWriterCore(outputContext, writerSet, writerEntityType, writeFeed); }
/// <summary> /// Asynchronously create ATOM output context. /// </summary> /// <param name="format">The format to create the output context for.</param> /// <param name="message">The message to use.</param> /// <param name="encoding">The encoding to use.</param> /// <param name="messageWriterSettings">Configuration settings of the OData writer.</param> /// <param name="writingResponse">true if writing a response message; otherwise false.</param> /// <param name="model">The model to use.</param> /// <param name="urlResolver">The optional URL resolver to perform custom URL resolution for URLs written to the payload.</param> /// <returns>Task which when completed returns the newly created output context.</returns> internal static Task<ODataOutputContext> CreateAsync( ODataFormat format, ODataMessage message, Encoding encoding, ODataMessageWriterSettings messageWriterSettings, bool writingResponse, IEdmModel model, IODataUrlResolver urlResolver) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(format == ODataFormat.Atom, "This method only supports the ATOM format."); Debug.Assert(message != null, "message != null"); Debug.Assert(messageWriterSettings != null, "messageWriterSettings != null"); return message.GetStreamAsync() .FollowOnSuccessWith( (streamTask) => (ODataOutputContext)new ODataAtomOutputContext( format, streamTask.Result, encoding, messageWriterSettings, writingResponse, false, model, urlResolver)); }