/// <summary> /// Initializes a new instance of the <see cref="FeedAndEntryMaterializerAdapter"/> class. Used for tests so no ODataMessageReader is required /// </summary> /// <param name="odataFormat">The format of the reader.</param> /// <param name="reader">The reader.</param> /// <param name="model">The model.</param> /// <param name="mergeOption">The mergeOption.</param> internal FeedAndEntryMaterializerAdapter(ODataFormat odataFormat, ODataReaderWrapper reader, ClientEdmModel model, MergeOption mergeOption) { this.readODataFormat = odataFormat; this.clientEdmModel = model; this.mergeOption = mergeOption; this.reader = reader; this.currentEntry = null; this.currentFeed = null; this.feedEntries = null; }
/// <summary> /// Initializes a new instance of the <see cref="ODataReaderEntityMaterializer" /> class. /// </summary> /// <param name="odataMessageReader">The odata message reader.</param> /// <param name="reader">The reader.</param> /// <param name="materializerContext">The materializer context.</param> /// <param name="entityTrackingAdapter">The entity tracking adapter.</param> /// <param name="queryComponents">The query components.</param> /// <param name="expectedType">The expected type.</param> /// <param name="materializeEntryPlan">The materialize entry plan.</param> public ODataReaderEntityMaterializer( ODataMessageReader odataMessageReader, ODataReaderWrapper reader, IODataMaterializerContext materializerContext, EntityTrackingAdapter entityTrackingAdapter, QueryComponents queryComponents, Type expectedType, ProjectionPlan materializeEntryPlan) : base(materializerContext, entityTrackingAdapter, queryComponents, expectedType, materializeEntryPlan) { this.messageReader = odataMessageReader; this.feedEntryAdapter = new FeedAndEntryMaterializerAdapter(odataMessageReader, reader, materializerContext.Model, entityTrackingAdapter.MergeOption); }
public void TestConfigureAction <T>(Func <DataServiceClientResponsePipelineConfiguration, ODataReaderState> setup, Action <T> verify) where T : ODataItem, new() { var item = new T(); var responsePipeline = new DataServiceClientResponsePipelineConfiguration(new DataServiceContext(new Uri("http://www.foo.com"))); var readerState = setup(responsePipeline); var reader = new TestODataReader() { new TestODataReaderItem(readerState, item) }; var odataReaderWrapper = ODataReaderWrapper.CreateForTest(reader, responsePipeline); odataReaderWrapper.Read(); verify(item); }
/// <summary> /// Initializes a new instance of the <see cref="ODataLoadNavigationPropertyMaterializer" /> class. /// </summary> /// <param name="odataMessageReader">The odata message reader.</param> /// <param name="reader">The reader.</param> /// <param name="materializerContext">The materializer context.</param> /// <param name="entityTrackingAdapter">The entity tracking adapter.</param> /// <param name="queryComponents">The query components.</param> /// <param name="expectedType">The expected type.</param> /// <param name="materializeEntryPlan">The materialize entry plan.</param> /// <param name="responseInfo">LoadProperty Response Info object.</param> public ODataLoadNavigationPropertyMaterializer( ODataMessageReader odataMessageReader, ODataReaderWrapper reader, IODataMaterializerContext materializerContext, EntityTrackingAdapter entityTrackingAdapter, QueryComponents queryComponents, Type expectedType, ProjectionPlan materializeEntryPlan, LoadPropertyResponseInfo responseInfo) : base(odataMessageReader, reader, materializerContext, entityTrackingAdapter, queryComponents, expectedType, materializeEntryPlan) { this.responseInfo = responseInfo; this.items = new List <object>(); }
public void NoEventShouldBeFiredWhenReadIsFalse() { bool eventFiredIncorrectly = false; TestODataReader reader = new TestODataReader() { new TestODataReaderItem(ODataReaderState.ResourceStart, new ODataResource()) }; reader.ReadFunc = () => false; var responsePipeline = new DataServiceClientResponsePipelineConfiguration(new DataServiceContext(new Uri("http://www.foo.com"))); responsePipeline.OnEntryStarted((ReadingEntryArgs args) => eventFiredIncorrectly = true); var odataReaderWrapper = ODataReaderWrapper.CreateForTest(reader, responsePipeline); odataReaderWrapper.Read(); Assert.IsFalse(eventFiredIncorrectly); }
/// <summary> /// This method is for parsing CUD operation payloads which should contain /// 1 a single entry /// 2 An Error /// </summary> /// <param name="message">the message for the payload</param> /// <param name="responseInfo">The current ResponseInfo object</param> /// <param name="expectedType">The expected type</param> /// <returns>the MaterializerEntry that was read</returns> internal static MaterializerEntry ParseSingleEntityPayload(IODataResponseMessage message, ResponseInfo responseInfo, Type expectedType) { ODataPayloadKind messageType = ODataPayloadKind.Resource; using (ODataMessageReader messageReader = CreateODataMessageReader(message, responseInfo, ref messageType)) { IEdmType edmType = responseInfo.TypeResolver.ResolveExpectedTypeForReading(expectedType); ODataReaderWrapper reader = ODataReaderWrapper.Create(messageReader, messageType, edmType, responseInfo.ResponsePipeline); FeedAndEntryMaterializerAdapter parser = new FeedAndEntryMaterializerAdapter(messageReader, reader, responseInfo.Model, responseInfo.MergeOption); ODataResource entry = null; bool readFeed = false; while (parser.Read()) { readFeed |= parser.CurrentFeed != null; if (parser.CurrentEntry != null) { if (entry != null) { throw new InvalidOperationException(DSClient.Strings.AtomParser_SingleEntry_MultipleFound); } entry = parser.CurrentEntry; } } if (entry == null) { if (readFeed) { throw new InvalidOperationException(DSClient.Strings.AtomParser_SingleEntry_NoneFound); } else { throw new InvalidOperationException(DSClient.Strings.AtomParser_SingleEntry_ExpectedFeedOrEntry); } } return(MaterializerEntry.GetEntry(entry)); } }
internal List <KeyValuePair <string, object> > TestValidReadWithAllHooked(Func <ODataReader> createOdataReader) { List <KeyValuePair <string, object> > results = new List <KeyValuePair <string, object> >(); var odataReader = createOdataReader(); DataServiceContext context = new DataServiceContext(new Uri("http://www.foo.com")); // context.EnableAtom = true; var responsePipeline = new DataServiceClientResponsePipelineConfiguration(context); responsePipeline.OnEntryEnded(args => results.Add(new KeyValuePair <string, object>("OnEntryEnded", args))); responsePipeline.OnEntryStarted(args => results.Add(new KeyValuePair <string, object>("OnEntryStarted", args))); responsePipeline.OnFeedStarted(args => results.Add(new KeyValuePair <string, object>("OnFeedStarted", args))); responsePipeline.OnFeedEnded(args => results.Add(new KeyValuePair <string, object>("OnFeedEnded", args))); responsePipeline.OnNestedResourceInfoEnded(args => results.Add(new KeyValuePair <string, object>("OnNestedResourceInfoEnded", args))); responsePipeline.OnNestedResourceInfoStarted(args => results.Add(new KeyValuePair <string, object>("OnNestedResourceInfoStarted", args))); var odataReaderTracker = ODataReaderWrapper.CreateForTest(odataReader, responsePipeline); while (odataReaderTracker.Read()) { } return(results); }
public void ValidateShortIntegrationFeedReading() { var initialFeed = new ODataResourceSet() { Id = new Uri("http://services.odata.org/OData/OData.svc/Products") }; var productItem = new ODataResource() { Id = new Uri("http://services.odata.org/OData/OData.svc/Products(0)") }; productItem.Properties = new ODataProperty[] { new ODataProperty() { Name = "Id", Value = 0 } }; var categoryNavigationLink = new ODataNestedResourceInfo() { Name = "Category" }; var categoryItem = new ODataResource() { Id = new Uri("http://services.odata.org/OData/OData.svc/Categories(0)") }; categoryItem.Properties = new ODataProperty[] { new ODataProperty() { Name = "Id", Value = 0 } }; var productsNavigationLink = new ODataNestedResourceInfo() { Name = "Products" }; var supplierNavigationLink = new ODataNestedResourceInfo() { Name = "Supplier" }; var testODataReader = new TestODataReader() { new TestODataReaderItem(ODataReaderState.ResourceSetStart, initialFeed), new TestODataReaderItem(ODataReaderState.ResourceStart, productItem), new TestODataReaderItem(ODataReaderState.NestedResourceInfoStart, categoryNavigationLink), new TestODataReaderItem(ODataReaderState.ResourceStart, categoryItem), new TestODataReaderItem(ODataReaderState.NestedResourceInfoStart, productsNavigationLink), new TestODataReaderItem(ODataReaderState.NestedResourceInfoEnd, productsNavigationLink), new TestODataReaderItem(ODataReaderState.ResourceEnd, categoryItem), new TestODataReaderItem(ODataReaderState.NestedResourceInfoEnd, categoryNavigationLink), new TestODataReaderItem(ODataReaderState.NestedResourceInfoStart, supplierNavigationLink), new TestODataReaderItem(ODataReaderState.NestedResourceInfoEnd, supplierNavigationLink), new TestODataReaderItem(ODataReaderState.ResourceEnd, productItem), new TestODataReaderItem(ODataReaderState.ResourceSetEnd, initialFeed), }; ClientEdmModel clientEdmModel = new ClientEdmModel(ODataProtocolVersion.V4); var responsePipeline = new DataServiceClientResponsePipelineConfiguration(new DataServiceContext()); var odataReaderWrapper = ODataReaderWrapper.CreateForTest(testODataReader, responsePipeline); FeedAndEntryMaterializerAdapter reader = new FeedAndEntryMaterializerAdapter(ODataFormat.Json, odataReaderWrapper, clientEdmModel, MergeOption.OverwriteChanges); int readCounter = 0; while (reader.Read()) { readCounter++; } readCounter.Should().Be(1); }
/// <summary> /// Creates an <see cref="ODataMaterializer"/> for a response. /// </summary> /// <param name="responseMessage">The response message.</param> /// <param name="responseInfo">The response context.</param> /// <param name="materializerType">The type to materialize.</param> /// <param name="queryComponents">The query components for the request.</param> /// <param name="plan">The projection plan.</param> /// <param name="payloadKind">expected payload kind.</param> /// <returns>A materializer specialized for the given response.</returns> public static ODataMaterializer CreateMaterializerForMessage( IODataResponseMessage responseMessage, ResponseInfo responseInfo, Type materializerType, QueryComponents queryComponents, ProjectionPlan plan, ODataPayloadKind payloadKind) { ODataMessageReader messageReader = CreateODataMessageReader(responseMessage, responseInfo, ref payloadKind); ODataMaterializer result; IEdmType edmType = null; try { ODataMaterializerContext materializerContext = new ODataMaterializerContext(responseInfo); // Since in V1/V2, astoria client allowed Execute<object> and depended on the typeresolver or the wire type name // to get the clr type to materialize. Hence if we see the materializer type as object, we should set the edmtype // to null, since there is no expected type. if (materializerType != typeof(System.Object)) { edmType = responseInfo.TypeResolver.ResolveExpectedTypeForReading(materializerType); } if (payloadKind == ODataPayloadKind.Property && edmType != null) { if (edmType.TypeKind.IsStructured()) { payloadKind = ODataPayloadKind.Resource; } else if (edmType.TypeKind == EdmTypeKind.Collection && (edmType as IEdmCollectionType).ElementType.IsStructured()) { payloadKind = ODataPayloadKind.ResourceSet; } } if (payloadKind == ODataPayloadKind.Resource || payloadKind == ODataPayloadKind.ResourceSet) { // In V1/V2, we allowed System.Object type to be allowed to pass to ExecuteQuery. // Hence we need to explicitly check for System.Object to allow this if (edmType != null && !edmType.TypeKind.IsStructured()) { throw DSClient.Error.InvalidOperation(DSClient.Strings.AtomMaterializer_InvalidNonEntityType(materializerType.FullName)); } ODataReaderWrapper reader = ODataReaderWrapper.Create(messageReader, payloadKind, edmType, responseInfo.ResponsePipeline); EntityTrackingAdapter entityTrackingAdapter = new EntityTrackingAdapter(responseInfo.EntityTracker, responseInfo.MergeOption, responseInfo.Model, responseInfo.Context); LoadPropertyResponseInfo loadPropertyResponseInfo = responseInfo as LoadPropertyResponseInfo; if (loadPropertyResponseInfo != null) { result = new ODataLoadNavigationPropertyMaterializer( messageReader, reader, materializerContext, entityTrackingAdapter, queryComponents, materializerType, plan, loadPropertyResponseInfo); } else { result = new ODataReaderEntityMaterializer( messageReader, reader, materializerContext, entityTrackingAdapter, queryComponents, materializerType, plan); } } else { switch (payloadKind) { case ODataPayloadKind.Value: result = new ODataValueMaterializer(messageReader, materializerContext, materializerType, queryComponents.SingleResult); break; case ODataPayloadKind.Collection: result = new ODataCollectionMaterializer(messageReader, materializerContext, materializerType, queryComponents.SingleResult); break; case ODataPayloadKind.Property: case ODataPayloadKind.IndividualProperty: // Top level properties cannot be of entity type. if (edmType != null && (edmType.TypeKind == EdmTypeKind.Entity || edmType.TypeKind == EdmTypeKind.Complex)) { throw DSClient.Error.InvalidOperation(DSClient.Strings.AtomMaterializer_InvalidEntityType(materializerType.FullName)); } result = new ODataPropertyMaterializer(messageReader, materializerContext, materializerType, queryComponents.SingleResult); break; case ODataPayloadKind.EntityReferenceLinks: case ODataPayloadKind.EntityReferenceLink: result = new ODataLinksMaterializer(messageReader, materializerContext, materializerType, queryComponents.SingleResult); break; case ODataPayloadKind.Error: var odataError = messageReader.ReadError(); throw new ODataErrorException(odataError.Message, odataError); default: throw DSClient.Error.InvalidOperation(DSClient.Strings.AtomMaterializer_InvalidResponsePayload(XmlConstants.DataWebNamespace)); } } return(result); } catch (Exception ex) { if (CommonUtil.IsCatchableExceptionType(ex)) { // Dispose the message reader in all error scenarios. messageReader.Dispose(); } throw; } }
/// <summary> /// Initializes a new instance of the <see cref="FeedAndEntryMaterializerAdapter"/> class. /// </summary> /// <param name="messageReader">The messageReader that is used to get the format of the reader.</param> /// <param name="reader">The reader.</param> /// <param name="model">The model.</param> /// <param name="mergeOption">The mergeOption.</param> internal FeedAndEntryMaterializerAdapter(ODataMessageReader messageReader, ODataReaderWrapper reader, ClientEdmModel model, MergeOption mergeOption) : this(ODataUtils.GetReadFormat(messageReader), reader, model, mergeOption) { }