private void TestAndMeasure(string propertyType) { var entry = GenerateEntry(propertyType); var entitySet = Model.EntityContainer.FindEntitySet(propertyType); foreach (var iteration in Benchmark.Iterations) { // Reuse the same stream WriteStream.Seek(0, SeekOrigin.Begin); using (iteration.StartMeasurement()) { using (var messageWriter = ODataMessageHelper.CreateMessageWriter(WriteStream, Model, ODataMessageKind.Response, isFullValidation: true)) { ODataWriter writer = messageWriter.CreateODataResourceSetWriter(entitySet, entitySet.EntityType()); writer.WriteStart(new ODataResourceSet { Id = new Uri("http://www.odata.org/Perf.svc") }); for (int i = 0; i < NumberOfEntries; ++i) { writer.WriteStart(entry); writer.WriteEnd(); } writer.WriteEnd(); writer.Flush(); } } } }
public void VerifyCanSendRequestPayloadSyncTest() { var request = new ClientHttpRequestMessage(new Uri(TestDemoService.ServiceBaseUri, "Products")); request.Method = ODataConstants.MethodPost; using (ODataMessageWriter messageWriter = new ODataMessageWriter( request, new ODataMessageWriterSettings(), TestUtils.GetServiceModel(TestDemoService.ServiceBaseUri))) { ODataWriter writer = messageWriter.CreateODataEntryWriter(); writer.WriteStart(new ODataEntry() { TypeName = "DataServiceProviderDemo.Product", Properties = new ODataProperty[] { new ODataProperty { Name = "ID", Value = 42 } } }); writer.WriteEnd(); writer.Flush(); } var response = request.GetResponse(); Assert.AreEqual(201, response.StatusCode); }
private void WriteTopLevelEntry(ODataMessageWriterTestWrapper messageWriter, ODataResource entry) { ExceptionUtilities.CheckArgumentNotNull(messageWriter, "messageWriter"); ODataWriter entryWriter = messageWriter.CreateODataResourceWriter(); this.WriteEntry(entryWriter, entry); entryWriter.Flush(); }
private static string WriteJsonLightEntryForUndeclared(bool isOpenType, Action <ODataWriter> writeAction, bool throwOnUndeclaredProperty = true) { EdmModel model = new EdmModel(); AddAndGetComplexType(model); EdmEntityType entityType = AddAndGetEntityType(model); if (isOpenType) { entityType = AddAndGetOpenEntityType(model); } var entitySet = GetEntitySet(model, entityType); var requestUri = new Uri("http://temp.org/FakeSet('parent')"); var odataUri = new ODataUri { RequestUri = requestUri }; odataUri.Path = new ODataUriParser(model, new Uri("http://temp.org/"), requestUri).ParsePath(); var stream = new MemoryStream(); var message = new InMemoryMessage { Stream = stream }; var settings = new ODataMessageWriterSettings { Version = ODataVersion.V4 }; if (!throwOnUndeclaredProperty) { settings.Validations &= ~ValidationKinds.ThrowOnUndeclaredPropertyForNonOpenType; } settings.ODataUri = odataUri; settings.SetServiceDocumentUri(new Uri("http://temp.org")); settings.SetContentType(ODataFormat.Json); settings.SetContentType("application/json;odata.metadata=full", null); ODataMessageWriter messageWriter; messageWriter = new ODataMessageWriter((IODataResponseMessage)message, settings, model); ODataWriter writer = null; writer = messageWriter.CreateODataResourceWriter(entitySet, entityType); if (writeAction != null) { writeAction(writer); } writer.Flush(); var actual = Encoding.UTF8.GetString(stream.ToArray()); return(actual); }
public static void WriteODataFeed(IEdmModel model, Stream stream) { // Create a ODataEntry var entry = new ODataEntry() { Properties = new List <ODataProperty>() { new ODataProperty { Name = "ProductId", Value = 100 }, new ODataProperty { Name = "Name", Value = "The World" }, new ODataProperty { Name = "SkinColor", Value = new ODataEnumValue("Green", DefaultNamespace + ".Color") }, new ODataProperty { Name = "UserAccess", Value = new ODataEnumValue("ReadWrite, Execute", DefaultNamespace + ".AccessLevel") } } }; ODataMessageWriterSettings writerSettings = new ODataMessageWriterSettings(); writerSettings.ODataUri = new ODataUri() { ServiceRoot = ServiceRootUri }; writerSettings.PayloadBaseUri = ServiceRootUri; writerSettings.SetContentType("application/json;odata.metadata=full", Encoding.UTF8.WebName); writerSettings.AutoComputePayloadMetadataInJson = true; var responseMessage = new ODataResponseMessage(stream); using (var messageWriter = new ODataMessageWriter(responseMessage, writerSettings, model)) { IEdmEntitySet entitySet = model.FindDeclaredEntitySet("Products"); ODataWriter feedWriter = messageWriter.CreateODataFeedWriter(entitySet); var feed = new ODataFeed { Id = new Uri(ServiceRootUri, "Products") }; feedWriter.WriteStart(feed); feedWriter.WriteStart(entry); feedWriter.WriteEnd(); feedWriter.WriteEnd(); feedWriter.Flush(); } }
public override void WriteObject(object graph, ODataMessageWriter messageWriter, ODataSerializerContext writeContext) { if (messageWriter == null) { throw Error.ArgumentNull("messageWriter"); } ODataWriter writer = messageWriter.CreateODataFeedWriter(); WriteObjectInline(graph, writer, writeContext); writer.Flush(); }
public void FatalExceptionTest() { ODataResource entry = ObjectModelUtils.CreateDefaultEntry(); this.CombinatorialEngineProvider.RunCombinations( new ODataItem[] { entry }, new bool[] { true, false }, // flush // TODO: also enable this test for the sync scenarios this.WriterTestConfigurationProvider.ExplicitFormatConfigurations.Where(tc => !tc.Synchronous), (payload, flush, testConfiguration) => { testConfiguration = testConfiguration.Clone(); testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri); using (var memoryStream = new TestStream()) using (var messageWriter = TestWriterUtils.CreateMessageWriter(memoryStream, testConfiguration, this.Assert)) { ODataWriter writer = messageWriter.CreateODataWriter(isFeed: false); ODataWriterCoreInspector inspector = new ODataWriterCoreInspector(writer); // close the memory stream so that any attempt to flush will cause a fatal error memoryStream.CloseInner(); // write the payload and call FlushAsync() to trigger a fatal exception Exception ex = TestExceptionUtils.RunCatching(() => TestWriterUtils.WritePayload(messageWriter, writer, true, entry)); this.Assert.IsNotNull(ex, "Expected exception but none was thrown."); NotSupportedException notSupported = null; #if SILVERLIGHT || WINDOWS_PHONE var baseEx = ex.GetBaseException(); this.Assert.IsNotNull(baseEx, "BaseException of exception:" + ex.ToString() + " should not be null"); notSupported = baseEx as NotSupportedException; this.Assert.IsNotNull(notSupported, "Expected NotSupportedException but " + baseEx.GetType().FullName + " was reported."); #else notSupported = TestExceptionUtils.UnwrapAggregateException(ex, this.Assert) as NotSupportedException; this.Assert.IsNotNull(notSupported, "Expected NotSupportedException but " + ex.ToString() + " was reported."); #endif this.Assert.AreEqual("Stream does not support writing.", notSupported.Message, "Did not find expected error message."); this.Assert.IsTrue(inspector.IsInErrorState, "Writer is not in expected 'Error' state."); if (flush) { // Flush should work in error state. writer.Flush(); } // in all cases we have to be able to dispose the writer without problems. } }); }
private static void WriteOdataEntity(ITableEntity entity, TableOperationType operationType, OperationContext ctx, ODataWriter writer, TableRequestOptions options) { ODataEntry entry = new ODataEntry() { Properties = GetPropertiesWithKeys(entity, ctx, operationType, options), TypeName = "account.sometype" }; entry.SetAnnotation(new SerializationTypeNameAnnotation { TypeName = null }); writer.WriteStart(entry); writer.WriteEnd(); writer.Flush(); }
private static void WriteOdataEntity(ITableEntity entity, TableOperationType operationType, OperationContext ctx, ODataWriter writer) { ODataEntry entry = new ODataEntry() { Properties = GetPropertiesWithKeys(entity, ctx) }; if (operationType != TableOperationType.Insert && operationType != TableOperationType.Retrieve) { entry.ETag = entity.ETag; } writer.WriteStart(entry); writer.WriteEnd(); writer.Flush(); }
public void WriteFeed() { using (var messageWriter = ODataMessageHelper.CreateMessageWriter(WriteStream, Model, ODataMessageKind.Response, isFullValidation: true)) { ODataWriter writer = messageWriter.CreateODataResourceSetWriter(entitySet, entitySet.EntityType()); writer.WriteStart(new ODataResourceSet { Id = new Uri("http://www.odata.org/Perf.svc") }); for (int i = 0; i < NumberOfEntries; ++i) { writer.WriteStart(entry); writer.WriteEnd(); } writer.WriteEnd(); writer.Flush(); } }
/// <summary> /// Writes an OData Feed with number <see cref="numberOfEntries"/> of entries <see cref="entry"/> /// </summary> /// <param name="writeStream"></param> /// <param name="edmModel"></param> /// <param name="numberOfEntries"></param> /// <param name="innerWrite"></param> /// <param name="entitySet"></param> /// <returns>The payload size</returns> protected Int64 WriteFeed(Stream writeStream, IEdmModel edmModel, long numberOfEntries, Action <ODataWriter> innerWrite, IEdmEntitySetBase entitySet) { using (var messageWriter = ODataMessageHelper.CreateMessageWriter(writeStream, edmModel)) { ODataWriter writer = messageWriter.CreateODataResourceSetWriter(entitySet); writer.WriteStart(new ODataResourceSet { Id = new Uri("http://www.odata.org/Perf.svc") }); for (long i = 0; i < numberOfEntries; ++i) { innerWrite(writer); } writer.WriteEnd(); writer.Flush(); } return(writeStream.Length); // return payload size }
private static string WriteJsonLightEntry(IEdmModel model, IEdmEntitySet entitySet, Action <ODataWriter> writeAction, bool isFullMetadata = false) { var stream = new MemoryStream(); var message = new InMemoryMessage { Stream = stream }; var settings = new ODataMessageWriterSettings { Version = ODataVersion.V4 }; var odataUri = new ODataUri { ServiceRoot = ServiceRoot }; odataUri.Path = new ODataUriParser(model, ServiceRoot, new Uri(ServiceRoot + "/EntitySet")).ParsePath(); settings.ODataUri = odataUri; settings.SetServiceDocumentUri(ServiceRoot); settings.SetContentType(ODataFormat.Json); if (isFullMetadata) { settings.SetContentType("application/json;odata.metadata=full", null); } else { settings.SetContentType("application/json;odata.metadata=minimal", null); } var messageWriter = new ODataMessageWriter((IODataResponseMessage)message, settings, model); ODataWriter writer = null; writer = messageWriter.CreateODataResourceWriter(entitySet); if (writeAction != null) { writeAction(writer); } writer.Flush(); var actual = Encoding.UTF8.GetString(stream.ToArray()); return(actual); }
/// <summary> /// Parses incoming feed/entry/property queries, resolves against the data store and formulates the response. /// </summary> /// <returns>Stream containing the query results if successful, otherwise an error.</returns> public Stream ProcessGetQuery(string requestUri) { object queryResults = null; QueryContext queryContext; try { queryContext = this.GetDefaultQueryContext(); queryResults = queryContext.ResolveQuery(this.Model, this.DataContext); } catch (Exception error) { return(this.WriteErrorResponse(400, error)); } return(this.WriteResponse(200, (messageWriter, writerSettings, message) => { IEdmEntitySet entitySet = queryContext.ResolveEntitySet(); ODataPathSegment lastSegment = queryContext.QueryPath.LastSegment; var expandedProperties = Enumerable.Empty <string>(); if (lastSegment is EntitySetSegment) { ODataWriter resultWriter = messageWriter.CreateODataFeedWriter(entitySet); ResponseWriter.WriteFeed(resultWriter, queryResults as IQueryable, entitySet, this.Model, writerSettings.Version.GetValueOrDefault(), expandedProperties); resultWriter.Flush(); } else if (lastSegment is KeySegment) { ODataWriter resultWriter = messageWriter.CreateODataEntryWriter(entitySet); ResponseWriter.WriteEntry(resultWriter, queryResults, entitySet, this.Model, writerSettings.Version.GetValueOrDefault(), expandedProperties); resultWriter.Flush(); } else if (lastSegment is PropertySegment) { ODataProperty property = ODataObjectModelConverter.CreateODataProperty(queryResults, (lastSegment as PropertySegment).Property.Name); messageWriter.WriteProperty(property); } else { throw new ODataErrorException("Unsupported URI segment " + lastSegment.GetType()); } })); }
public void WriteAfterExceptionTest() { // create a default entry and then set both read and edit links to null to provoke an exception during writing ODataResource faultyEntry = ObjectModelUtils.CreateDefaultEntry(); this.Assert.IsNull(faultyEntry.EditLink, "entry.EditLink == null"); ODataResource defaultEntry = ObjectModelUtils.CreateDefaultEntry(); ODataResourceSet defaultFeed = ObjectModelUtils.CreateDefaultFeed(); this.CombinatorialEngineProvider.RunCombinations( new ODataItem[] { faultyEntry }, new ODataItem[] { defaultFeed, defaultEntry }, this.WriterTestConfigurationProvider.ExplicitFormatConfigurations, (faultyPayload, contentPayload, testConfiguration) => { testConfiguration = testConfiguration.Clone(); testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri); using (var memoryStream = new TestStream()) using (var messageWriter = TestWriterUtils.CreateMessageWriter(memoryStream, testConfiguration, this.Assert)) { ODataWriter writer = messageWriter.CreateODataWriter(isFeed: false); ODataWriterCoreInspector inspector = new ODataWriterCoreInspector(writer); // write the invalid entry and expect an exception this.Assert.ExpectedException( () => TestWriterUtils.WritePayload(messageWriter, writer, false, faultyEntry), ODataExpectedExceptions.ODataException("WriterValidationUtils_EntriesMustHaveNonEmptyId"), this.ExceptionVerifier); this.Assert.IsTrue(inspector.IsInErrorState, "Writer is not in expected 'error' state."); // now write some non-error content which is invalid to do Exception ex = TestExceptionUtils.RunCatching(() => TestWriterUtils.WritePayload(messageWriter, writer, false, contentPayload)); ex = TestExceptionUtils.UnwrapAggregateException(ex, this.Assert); this.Assert.IsNotNull(ex, "Expected exception but none was thrown"); this.Assert.IsTrue(ex is ODataException, "Expected an ODataException instance but got a " + ex.GetType().FullName + "."); this.Assert.IsTrue(ex.Message.Contains("Cannot transition from state 'Error' to state "), "Did not find expected start of error message."); this.Assert.IsTrue(ex.Message.Contains("Nothing can be written once the writer entered the error state."), "Did not find expected end of error message in '" + ex.Message + "'."); this.Assert.IsTrue(inspector.IsInErrorState, "Writer is not in expected 'error' state."); writer.Flush(); } }); }
private static void WriteOdataEntity(ITableEntity entity, TableOperationType operationType, OperationContext ctx, ODataWriter writer) { ODataEntry entry = new ODataEntry() { Properties = GetPropertiesWithKeys(entity, ctx, operationType), TypeName = "account.sometype" }; if (operationType != TableOperationType.Insert && operationType != TableOperationType.Retrieve) { entry.ETag = entity.ETag; } entry.SetAnnotation(new SerializationTypeNameAnnotation { TypeName = null }); writer.WriteStart(entry); writer.WriteEnd(); writer.Flush(); }
/// <inheritdoc /> public override async Task WriteObjectAsync(object graph, Type type, ODataMessageWriter messageWriter, ODataSerializerContext writeContext) { if (messageWriter == null) { throw Error.ArgumentNull("messageWriter"); } if (writeContext == null) { throw Error.ArgumentNull("writeContext"); } IEdmTypeReference edmType = writeContext.GetEdmType(graph, type); Contract.Assert(edmType != null); IEdmNavigationSource navigationSource = writeContext.NavigationSource; ODataWriter writer = messageWriter.CreateODataResourceWriter(navigationSource, edmType.ToStructuredType()); await WriteObjectInlineAsync(graph, edmType, writer, writeContext); writer.Flush(); }
public void WriterShouldNotIncludeTypeNameForCollectionOfDerivedType() { // JSON Light: writer doesn't include type name for collection of derived type // If I have a collection property declared in metadata as Collection(Edm.Geography), // and at serialization type, it's clearly a Collection(Edm.GeographyPoint), // we won't write the type name for that property by default (i.e., minimal metadata mode). var model = new EdmModel(); var entityType = new EdmEntityType("Var1", "Type"); entityType.AddKeys(entityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32)); entityType.AddProperty(new EdmStructuralProperty(entityType, "Geographies", new EdmCollectionTypeReference(new EdmCollectionType(EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.Geography, false))))); model.AddElement(entityType); var writerSettings = new ODataMessageWriterSettings(); writerSettings.SetContentType(ODataFormat.Json); writerSettings.EnableMessageStreamDisposal = false; var message = new InMemoryMessage { Stream = new MemoryStream() }; using (ODataMessageWriter odataMessageWriter = new ODataMessageWriter((IODataRequestMessage)message, writerSettings, model)) { ODataWriter odataWriter = odataMessageWriter.CreateODataResourceWriter(); odataWriter.WriteStart( new ODataResource { TypeName = "Var1.Type", Properties = new[] { new ODataProperty() { Name = "Id", Value = 1 }, new ODataProperty() { Name = "Geographies", Value = new ODataCollectionValue { Items = new[] { GeographyPoint.Create(0, 0), GeographyPoint.Create(1, 1), GeographyPoint.Create(2, 2) } } }, } }); odataWriter.WriteEnd(); odataWriter.Flush(); } message.Stream.Position = 0; var output = new StreamReader(message.Stream).ReadToEnd(); Assert.IsFalse(output.Contains("Collection(Edm.GeographyPoint)"), @"output.Contains(""Collection(Edm.GeographyPoint)"" == false"); }
private static string WriteJsonLightEntry(bool isRequest, Uri serviceDocumentUri, bool specifySet, ODataResource odataEntry, IEdmNavigationSource entitySet, IEdmStructuredType resourceType, ODataUri odataUri, Action <ODataWriter> writeAction = null, bool isResourceSet = false, EdmModel model = null, bool ValidatePropertyNames = true) { if (model == null) { model = new EdmModel(); model.AddElement(new EdmEntityContainer("Fake", "Container_sub")); } var stream = new MemoryStream(); var message = new InMemoryMessage { Stream = stream }; var settings = new ODataMessageWriterSettings { Version = ODataVersion.V4 }; settings.ODataUri = odataUri; settings.SetServiceDocumentUri(serviceDocumentUri); settings.SetContentType(ODataFormat.Json); settings.SetContentType("application/json;odata.metadata=full", null); if (!ValidatePropertyNames) { settings.Validations = ValidationKinds.None; } ODataMessageWriter messageWriter; if (isRequest) { messageWriter = new ODataMessageWriter((IODataRequestMessage)message, settings, model ?? TestUtils.WrapReferencedModelsToMainModel("Fake", "Container", model)); } else { messageWriter = new ODataMessageWriter((IODataResponseMessage)message, settings, model ?? TestUtils.WrapReferencedModelsToMainModel("Fake", "Container", model)); } ODataWriter writer = null; if (isResourceSet) { writer = messageWriter.CreateODataResourceSetWriter(entitySet as IEdmEntitySetBase, resourceType); } else { writer = messageWriter.CreateODataResourceWriter(specifySet ? entitySet : null, resourceType); } if (writeAction != null) { writeAction(writer); } else if (!isResourceSet) { writer.WriteStart(odataEntry); writer.WriteEnd(); } writer.Flush(); var actual = Encoding.UTF8.GetString(stream.ToArray()); return(actual); }
/// <summary> /// Writes collection value in body operation parameter. /// </summary> /// <param name="parameterWriter">The odata parameter writer.</param> /// <param name="operationParameter">The operation parameter.</param> /// <param name="edmCollectionType">The edm collection type.</param> private void WriteCollectionValueInBodyOperationParameter(ODataParameterWriter parameterWriter, BodyOperationParameter operationParameter, IEdmCollectionType edmCollectionType) { ClientEdmModel model = this.requestInfo.Model; var elementTypeKind = edmCollectionType.ElementType.TypeKind(); if (elementTypeKind == EdmTypeKind.Entity || elementTypeKind == EdmTypeKind.Complex) { ODataWriter feedWriter = parameterWriter.CreateResourceSetWriter(operationParameter.Name); feedWriter.WriteStart(new ODataResourceSet()); IEnumerator enumerator = ((ICollection)operationParameter.Value).GetEnumerator(); while (enumerator.MoveNext()) { Object collectionItem = enumerator.Current; if (collectionItem == null) { if (elementTypeKind == EdmTypeKind.Complex) { feedWriter.WriteStart((ODataResource)null); feedWriter.WriteEnd(); continue; } else { throw new NotSupportedException(Strings.Serializer_NullCollectionParamterItemValue(operationParameter.Name)); } } IEdmType edmItemType = model.GetOrCreateEdmType(collectionItem.GetType()); Debug.Assert(edmItemType != null, "edmItemType != null"); if (edmItemType.TypeKind != EdmTypeKind.Entity && edmItemType.TypeKind != EdmTypeKind.Complex) { throw new NotSupportedException(Strings.Serializer_InvalidCollectionParamterItemType(operationParameter.Name, edmItemType.TypeKind)); } Debug.Assert(model.GetClientTypeAnnotation(edmItemType).ElementType != null, "edmItemType.GetClientTypeAnnotation().ElementType != null"); ODataResourceWrapper entry = this.CreateODataResourceFromEntityOperationParameter(model.GetClientTypeAnnotation(edmItemType), collectionItem); Debug.Assert(entry != null, "entry != null"); ODataWriterHelper.WriteResource(feedWriter, entry); } feedWriter.WriteEnd(); feedWriter.Flush(); } else { ODataCollectionWriter collectionWriter = parameterWriter.CreateCollectionWriter(operationParameter.Name); ODataCollectionStart odataCollectionStart = new ODataCollectionStart(); collectionWriter.WriteStart(odataCollectionStart); IEnumerator enumerator = ((ICollection)operationParameter.Value).GetEnumerator(); while (enumerator.MoveNext()) { Object collectionItem = enumerator.Current; if (collectionItem == null) { collectionWriter.WriteItem(null); continue; } IEdmType edmItemType = model.GetOrCreateEdmType(collectionItem.GetType()); Debug.Assert(edmItemType != null, "edmItemType != null"); switch (edmItemType.TypeKind) { case EdmTypeKind.Primitive: { object primitiveItemValue = ODataPropertyConverter.ConvertPrimitiveValueToRecognizedODataType(collectionItem, collectionItem.GetType()); collectionWriter.WriteItem(primitiveItemValue); break; } case EdmTypeKind.Enum: { ODataEnumValue enumTmp = this.propertyConverter.CreateODataEnumValue(model.GetClientTypeAnnotation(edmItemType).ElementType, collectionItem, false); collectionWriter.WriteItem(enumTmp); break; } default: // EdmTypeKind.Entity // EdmTypeKind.Row // EdmTypeKind.EntityReference throw new NotSupportedException(Strings.Serializer_InvalidCollectionParamterItemType(operationParameter.Name, edmItemType.TypeKind)); } } collectionWriter.WriteEnd(); collectionWriter.Flush(); } }
public void DisposeAfterExceptionTest() { // create a default entry and then set both read and edit links to null to provoke an exception during writing ODataResource entry = ObjectModelUtils.CreateDefaultEntry(); this.Assert.IsNull(entry.EditLink, "entry.EditLink == null"); this.CombinatorialEngineProvider.RunCombinations( new ODataItem[] { entry }, new bool[] { true, false }, // writeError new bool[] { true, false }, // flush this.WriterTestConfigurationProvider.ExplicitFormatConfigurations.Where(c => c.IsRequest == false), (payload, writeError, flush, testConfiguration) => { testConfiguration = testConfiguration.Clone(); testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri); // try writing to a memory stream using (var memoryStream = new TestStream()) using (var messageWriter = TestWriterUtils.CreateMessageWriter(memoryStream, testConfiguration, this.Assert)) { ODataWriter writer = messageWriter.CreateODataWriter(isFeed: false); ODataWriterCoreInspector inspector = new ODataWriterCoreInspector(writer); try { // write the invalid entry and expect an exception TestExceptionUtils.ExpectedException( this.Assert, () => TestWriterUtils.WritePayload(messageWriter, writer, false, entry), ODataExpectedExceptions.ODataException("WriterValidationUtils_EntriesMustHaveNonEmptyId"), this.ExceptionVerifier); this.Assert.IsTrue(inspector.IsInErrorState, "Writer is not in expected 'error' state."); if (writeError) { // now write an error which is the only valid thing to do ODataAnnotatedError error = new ODataAnnotatedError { Error = new ODataError() { Message = "DisposeAfterExceptionTest error message." } }; Exception ex = TestExceptionUtils.RunCatching(() => TestWriterUtils.WritePayload(messageWriter, writer, false, error)); this.Assert.IsNull(ex, "Unexpected error '" + (ex == null ? "<none>" : ex.Message) + "' while writing an error."); this.Assert.IsTrue(inspector.IsInErrorState, "Writer is not in expected 'error' state."); } if (flush) { writer.Flush(); } } catch (ODataException oe) { if (writeError && !flush) { this.Assert.AreEqual("A writer or stream has been disposed with data still in the buffer. You must call Flush or FlushAsync before calling Dispose when some data has already been written.", oe.Message, "Did not find expected error message"); this.Assert.IsTrue(inspector.IsInErrorState, "Writer is not in expected 'error' state."); } else { this.Assert.Fail("Caught an unexpected ODataException: " + oe.Message + "."); } } } }); }
public override void Process(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage) { if (this.TryDispatch(requestMessage, responseMessage)) { return; } this.QueryContext.InitializeServerDrivenPaging(this.PreferenceContext); this.QueryContext.InitializeTrackingChanges(this.PreferenceContext); object queryResults = this.QueryContext.ResolveQuery(this.DataSource); if (queryResults == null) { // For individual property or $value if (this.QueryContext.Target.Property != null) { // Protocol 9.1.4 Response Code 204 No Content // A request returns 204 No Content if the requested resource has the null value, // or if the service applies a return=minimal preference. In this case, the response body MUST be empty. ResponseWriter.WriteEmptyResponse(responseMessage); return; } else { throw Utility.BuildException(HttpStatusCode.NotFound); } } // Handle the prefer of "odata.include-annotations", including it in response header if (!string.IsNullOrEmpty(this.PreferenceContext.IncludeAnnotations)) { responseMessage.AddPreferenceApplied(string.Format("{0}={1}", ServiceConstants.Preference_IncludeAnnotations, this.PreferenceContext.IncludeAnnotations)); } if (this.PreferenceContext.MaxPageSize.HasValue) { responseMessage.AddPreferenceApplied(string.Format("{0}={1}", ServiceConstants.Preference_MaxPageSize, this.QueryContext.appliedPageSize.Value)); } if (this.PreferenceContext.TrackingChanges) { responseMessage.AddPreferenceApplied(ServiceConstants.Preference_TrackChanging); } responseMessage.SetStatusCode(HttpStatusCode.OK); using (var messageWriter = this.CreateMessageWriter(responseMessage)) { IEdmNavigationSource navigationSource = this.QueryContext.Target.NavigationSource; IEnumerable iEnumerableResults = queryResults as IEnumerable; if (this.QueryContext.Target.IsReference && this.QueryContext.Target.TypeKind == EdmTypeKind.Collection) { // Query a $ref collection IList <ODataEntityReferenceLink> links = new List <ODataEntityReferenceLink>(); foreach (var iEnumerableResult in iEnumerableResults) { var link = new ODataEntityReferenceLink { Url = Utility.BuildLocationUri(this.QueryContext, iEnumerableResult), }; links.Add(link); } ODataEntityReferenceLinks linksCollection = new ODataEntityReferenceLinks() { Links = links, NextPageLink = this.QueryContext.NextLink }; linksCollection.InstanceAnnotations.Add(new ODataInstanceAnnotation("Links.Annotation", new ODataPrimitiveValue(true))); messageWriter.WriteEntityReferenceLinks(linksCollection); } else if (this.QueryContext.Target.IsReference && this.QueryContext.Target.TypeKind == EdmTypeKind.Entity) { // Query a $ref var link = new ODataEntityReferenceLink { Url = Utility.BuildLocationUri(this.QueryContext, queryResults), }; link.InstanceAnnotations.Add(new ODataInstanceAnnotation("Link.Annotation", new ODataPrimitiveValue(true))); messageWriter.WriteEntityReferenceLink(link); } else if (this.QueryContext.Target.NavigationSource != null && this.QueryContext.Target.TypeKind == EdmTypeKind.Collection) { // Query a feed IEdmEntitySetBase entitySet = navigationSource as IEdmEntitySetBase; IEdmEntityType entityType = this.QueryContext.Target.ElementType as IEdmEntityType; if (entitySet == null || entityType == null) { throw new InvalidOperationException("Invalid target when query feed."); } ODataWriter resultWriter = messageWriter.CreateODataFeedWriter(entitySet, entityType); ResponseWriter.WriteFeed(resultWriter, iEnumerableResults, entitySet, ODataVersion.V4, this.QueryContext.QuerySelectExpandClause, this.QueryContext.TotalCount, this.QueryContext.DeltaLink, this.QueryContext.NextLink, this.RequestHeaders); resultWriter.Flush(); } else if (this.QueryContext.Target.NavigationSource != null && this.QueryContext.Target.TypeKind == EdmTypeKind.Entity) { var currentETag = Utility.GetETagValue(queryResults); // if the current entity has ETag field if (currentETag != null) { string requestETag; if (Utility.TryGetIfNoneMatch(this.RequestHeaders, out requestETag) && (requestETag == ServiceConstants.ETagValueAsterisk || requestETag == currentETag)) { ResponseWriter.WriteEmptyResponse(responseMessage, HttpStatusCode.NotModified); return; } responseMessage.SetHeader(ServiceConstants.HttpHeaders.ETag, currentETag); } // Query a single entity IEdmEntityType entityType = this.QueryContext.Target.Type as IEdmEntityType; ODataWriter resultWriter = messageWriter.CreateODataEntryWriter(navigationSource, entityType); ResponseWriter.WriteEntry(resultWriter, queryResults, navigationSource, ODataVersion.V4, this.QueryContext.QuerySelectExpandClause, this.RequestHeaders); resultWriter.Flush(); } else if (this.QueryContext.Target.Property != null && !this.QueryContext.Target.IsRawValue) { // Query a individual property ODataProperty property = ODataObjectModelConverter.CreateODataProperty(queryResults, this.QueryContext.Target.Property.Name); messageWriter.WriteProperty(property); } else if (this.QueryContext.Target.IsRawValue) { // Query a $value or $count var propertyValue = ODataObjectModelConverter.CreateODataValue(queryResults); messageWriter.WriteValue(propertyValue); } else { throw Utility.BuildException(HttpStatusCode.NotImplemented); } } }
private void WriteEnd(ODataWriter writer, ODataReaderState expectedState) { this.expectedStates.Add(expectedState); writer.WriteEnd(); writer.Flush(); }