/// <inheritdoc /> public override void WriteObject(object graph, Type type, ODataMessageWriter messageWriter, ODataSerializerContext writeContext) { if (messageWriter == null) { throw Error.ArgumentNull("messageWriter"); } if (writeContext == null) { throw Error.ArgumentNull("writeContext"); } IEdmNavigationSource navigationSource = writeContext.NavigationSource; if (navigationSource == null) { throw new SerializationException(SRResources.NavigationSourceMissingDuringSerialization); } var path = writeContext.Path; if (path == null) { throw new SerializationException(SRResources.ODataPathMissing); } ODataWriter writer = messageWriter.CreateODataEntryWriter(navigationSource, path.EdmType as IEdmEntityType); WriteObjectInline(graph, navigationSource.EntityType().ToEdmTypeReference(isNullable: false), writer, writeContext); }
/// <summary> /// Writes the given object specified by the parameter graph as a part of an existing OData message using the given /// messageWriter and the writeContext. /// </summary> /// <param name="graph">The object to be written.</param> /// <param name="expectedType">The expected EDM type of the object represented by <paramref name="graph"/>.</param> /// <param name="writer">The <see cref="ODataDeltaWriter" /> to be used for writing.</param> /// <param name="writeContext">The <see cref="ODataSerializerContext"/>.</param> public virtual void WriteDeltaFeedInline(object graph, IEdmTypeReference expectedType, ODataDeltaWriter writer, ODataSerializerContext writeContext) { if (writer == null) { throw Error.ArgumentNull("writer"); } if (writeContext == null) { throw Error.ArgumentNull("writeContext"); } if (expectedType == null) { throw Error.ArgumentNull("expectedType"); } if (graph == null) { throw new SerializationException(Error.Format(SRResources.CannotSerializerNull, DeltaFeed)); } IEnumerable enumerable = graph as IEnumerable; // Data to serialize if (enumerable == null) { throw new SerializationException( Error.Format(SRResources.CannotWriteType, GetType().Name, graph.GetType().FullName)); } WriteFeed(enumerable, expectedType, writer, writeContext); }
/// <inheritdoc /> public override void WriteObject(object graph, Type type, ODataMessageWriter messageWriter, ODataSerializerContext writeContext) { if (messageWriter == null) { throw Error.ArgumentNull("messageWriter"); } if (writeContext == null) { throw Error.ArgumentNull("writeContext"); } if (graph == null) { throw new SerializationException(Error.Format(SRResources.CannotSerializerNull, DeltaFeed)); } IEdmEntitySetBase entitySet = writeContext.NavigationSource as IEdmEntitySetBase; if (entitySet == null) { throw new SerializationException(SRResources.EntitySetMissingDuringSerialization); } IEdmTypeReference feedType = writeContext.GetEdmType(graph, type); Contract.Assert(feedType != null); IEdmEntityTypeReference entityType = GetEntityType(feedType); ODataDeltaWriter writer = messageWriter.CreateODataDeltaWriter(entitySet, entityType.EntityDefinition()); WriteDeltaFeedInline(graph, feedType, writer, writeContext); }
/// <inheritdoc /> public override void WriteObjectInline(object graph, IEdmTypeReference expectedType, ODataWriter writer, ODataSerializerContext writeContext) { if (writer == null) { throw Error.ArgumentNull("writer"); } if (writeContext == null) { throw Error.ArgumentNull("writeContext"); } if (graph == null) { throw new SerializationException(Error.Format(SRResources.CannotSerializerNull, Entry)); } else { WriteEntry(graph, writer, writeContext); } }
private static Uri GetNestedNextPageLink(ODataSerializerContext writeContext, int pageSize) { Contract.Assert(writeContext.ExpandedEntity != null); IEdmNavigationSource sourceNavigationSource = writeContext.ExpandedEntity.NavigationSource; NavigationSourceLinkBuilderAnnotation linkBuilder = writeContext.Model.GetNavigationSourceLinkBuilder(sourceNavigationSource); Uri navigationLink = linkBuilder.BuildNavigationLink(writeContext.ExpandedEntity, writeContext.NavigationProperty); if (navigationLink != null) { //return ODataQueryOptions.GetNextPageLink(navigationLink, pageSize); throw new NotImplementedException("ODataQueryOptions"); } return null; }
/// <summary> /// Writes the given deltaDeletedEntry specified by the parameter graph as a part of an existing OData message using the given /// messageWriter and the writeContext. /// </summary> /// <param name="graph">The object to be written.</param> /// <param name="writer">The <see cref="ODataDeltaWriter" /> to be used for writing.</param> /// <param name="writeContext">The <see cref="ODataSerializerContext"/>.</param> public virtual void WriteDeltaDeletedEntry(object graph, ODataDeltaWriter writer, ODataSerializerContext writeContext) { EdmDeltaDeletedEntityObject edmDeltaDeletedEntity = graph as EdmDeltaDeletedEntityObject; if (edmDeltaDeletedEntity == null) { throw new SerializationException(Error.Format(SRResources.CannotWriteType, GetType().Name, graph.GetType().FullName)); } ODataDeltaDeletedEntry deltaDeletedEntry = new ODataDeltaDeletedEntry( edmDeltaDeletedEntity.Id, edmDeltaDeletedEntity.Reason); if (deltaDeletedEntry != null) { writer.WriteDeltaDeletedEntry(deltaDeletedEntry); } }
private void WriteFeed(IEnumerable enumerable, IEdmTypeReference feedType, ODataDeltaWriter writer, ODataSerializerContext writeContext) { Contract.Assert(writer != null); Contract.Assert(writeContext != null); Contract.Assert(enumerable != null); Contract.Assert(feedType != null); ODataDeltaFeed deltaFeed = CreateODataDeltaFeed(enumerable, feedType.AsCollection(), writeContext); if (deltaFeed == null) { throw new SerializationException(Error.Format(SRResources.CannotSerializerNull, DeltaFeed)); } // save this for later to support JSON odata.streaming. Uri nextPageLink = deltaFeed.NextPageLink; deltaFeed.NextPageLink = null; //Start writing of the Delta Feed writer.WriteStart(deltaFeed); //Iterate over all the entries present and select the appropriate write method. //Write method creates ODataDeltaDeletedEntry / ODataDeltaDeletedLink / ODataDeltaLink or ODataEntry. foreach (object entry in enumerable) { if (entry == null) { throw new SerializationException(SRResources.NullElementInCollection); } IEdmChangedObject edmChangedObject = entry as IEdmChangedObject; if (edmChangedObject == null) { throw new SerializationException(Error.Format(SRResources.CannotWriteType, GetType().Name, enumerable.GetType().FullName)); } switch (edmChangedObject.DeltaKind) { case EdmDeltaEntityKind.DeletedEntry: WriteDeltaDeletedEntry(entry, writer, writeContext); break; case EdmDeltaEntityKind.DeletedLinkEntry: WriteDeltaDeletedLink(entry, writer, writeContext); break; case EdmDeltaEntityKind.LinkEntry: WriteDeltaLink(entry, writer, writeContext); break; case EdmDeltaEntityKind.Entry: { IEdmEntityTypeReference elementType = GetEntityType(feedType); ODataEntityTypeSerializer entrySerializer = SerializerProvider.GetEdmTypeSerializer(elementType) as ODataEntityTypeSerializer; if (entrySerializer == null) { throw new SerializationException( Error.Format(SRResources.TypeCannotBeSerialized, elementType.FullName(), typeof(ODataOutputFormatter).Name)); } entrySerializer.WriteDeltaObjectInline(entry, elementType, writer, writeContext); break; } default: break; } } // Subtle and surprising behavior: If the NextPageLink property is set before calling WriteStart(feed), // the next page link will be written early in a manner not compatible with odata.streaming=true. Instead, if // the next page link is not set when calling WriteStart(feed) but is instead set later on that feed // object before calling WriteEnd(), the next page link will be written at the end, as required for // odata.streaming=true support. if (nextPageLink != null) { deltaFeed.NextPageLink = nextPageLink; } //End Writing of the Delta Feed writer.WriteEnd(); }
private void WriteResponseBody(OutputFormatterWriteContext context) { HttpContext httpContext = context.HttpContext; HttpRequest request = context.HttpContext.Request; HttpResponse response = context.HttpContext.Response; IEdmModel model = context.HttpContext.ODataFeature().Model; if (model == null) { throw Error.InvalidOperation(SRResources.RequestMustHaveModel); } object value = null; object graph = null; var objectResult = context.Object as PageResult <object>; if (objectResult != null) { value = objectResult.Items; graph = objectResult; } else { value = context.Object; graph = value; } var type = value.GetType(); ODataSerializer serializer = GetSerializer(type, value, context); IUrlHelper urlHelper = context.HttpContext.UrlHelper(); ODataPath path = httpContext.ODataFeature().Path; IEdmNavigationSource targetNavigationSource = path == null ? null : path.NavigationSource; string preferHeader = RequestPreferenceHelpers.GetRequestPreferHeader(request); string annotationFilter = null; if (!String.IsNullOrEmpty(preferHeader)) { ODataMessageWrapper messageWrapper = new ODataMessageWrapper(response.Body, response.Headers); messageWrapper.SetHeader(RequestPreferenceHelpers.PreferHeaderName, preferHeader); annotationFilter = messageWrapper.PreferHeader().AnnotationFilter; } IODataResponseMessage responseMessage = new ODataMessageWrapper(response.Body, response.Headers); if (annotationFilter != null) { responseMessage.PreferenceAppliedHeader().AnnotationFilter = annotationFilter; } Uri baseAddress = GetBaseAddress(request); ODataMessageWriterSettings writerSettings = _messageWriterSettings.Clone(); writerSettings.BaseUri = baseAddress; writerSettings.Version = ODataVersion.V4; writerSettings.Validations = writerSettings.Validations & ~ValidationKinds.ThrowOnUndeclaredPropertyForNonOpenType; string metadataLink = urlHelper.CreateODataLink(request, MetadataSegment.Instance); if (metadataLink == null) { throw new SerializationException(SRResources.UnableToDetermineMetadataUrl); } writerSettings.ODataUri = new ODataUri { ServiceRoot = baseAddress, // TODO: 1604 Convert webapi.odata's ODataPath to ODL's ODataPath, or use ODL's ODataPath. SelectAndExpand = httpContext.ODataFeature().SelectExpandClause, Path = (path == null) ? null : path.ODLPath //Path = (path == null || IsOperationPath(path)) ? null : path.ODLPath, }; #region 为OData添加缓存 使用的EF二级缓存 这里是先从缓存获取数据 //var queryResult = graph as IQueryable; //PageResult<object> target = null; //if (queryResult == null) //{ // target = graph as PageResult<object>; // if (target != null) queryResult = target.Items.AsQueryable(); //} //var isReadCache = queryResult != null || target != null; //var cacheValue = isReadCache?queryResult.CacheResult(context.HttpContext.RequestServices):null; //if (isReadCache&&target != null && cacheValue != null) //{ // var pageResult = cacheValue as IEnumerable<object>; // //long? count = target.Count.HasValue ? (long?)pageResult.LongCount() : null; // cacheValue = new PageResult<object>(pageResult, null, target.Count); //} //if (isReadCache&&cacheValue != null) graph = cacheValue; #endregion using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, writerSettings, model)) { ODataSerializerContext writeContext = new ODataSerializerContext() { Context = context.HttpContext, Url = urlHelper, NavigationSource = targetNavigationSource, Model = model, RootElementName = GetRootElementName(path) ?? "root", SkipExpensiveAvailabilityChecks = serializer.ODataPayloadKind == ODataPayloadKind.ResourceSet, Path = path, MetadataLevel = ODataMediaTypes.GetMetadataLevel(MediaTypeHeaderValue.Parse(context.ContentType.Value)), SelectExpandClause = request.ODataFeature().SelectExpandClause, }; serializer.WriteObject(graph, type, messageWriter, writeContext); #region 这里是往缓存中 存储数据 //if (isReadCache&&cacheValue == null) //{ // writeContext.Context.Response.Body.Position = 0; // StreamReader reder = new StreamReader(writeContext.Context.Response.Body); // var bodyStr = reder.ReadToEnd(); // JObject.Parse(bodyStr).TryGetValue("value",out JToken values); // cacheValue = values.ToObject(type.MarkListType()); // queryResult.CacheQuerable(cacheValue, writeContext.Context.RequestServices); //} #endregion } }
/// <summary> /// Creates an <see cref="ODataCollectionValue"/> for the enumerable represented by <paramref name="enumerable"/>. /// </summary> /// <param name="enumerable">The value of the collection to be created.</param> /// <param name="elementType">The element EDM type of the collection.</param> /// <param name="writeContext">The serializer context to be used while creating the collection.</param> /// <returns>The created <see cref="ODataCollectionValue"/>.</returns> public virtual ODataCollectionValue CreateODataCollectionValue(IEnumerable enumerable, IEdmTypeReference elementType, ODataSerializerContext writeContext) { if (writeContext == null) { throw Error.ArgumentNull("writeContext"); } if (elementType == null) { throw Error.ArgumentNull("elementType"); } var valueCollection = new List<object>(); if (enumerable != null) { ODataEdmTypeSerializer itemSerializer = null; foreach (object item in enumerable) { if (item == null) { if (elementType.IsNullable) { valueCollection.Add(null); continue; } throw new SerializationException(SRResources.NullElementInCollection); } IEdmTypeReference actualType = writeContext.GetEdmType(item, item.GetType()); Contract.Assert(actualType != null); itemSerializer = itemSerializer ?? SerializerProvider.GetEdmTypeSerializer(actualType); if (itemSerializer == null) { throw new SerializationException( Error.Format(SRResources.TypeCannotBeSerialized, actualType.FullName(), typeof(ODataOutputFormatter).Name)); } // ODataCollectionWriter expects the individual elements in the collection to be the underlying // values and not ODataValues. valueCollection.Add( itemSerializer.CreateODataValue(item, actualType, writeContext).GetInnerValue()); } } // Ideally, we'd like to do this: // string typeName = _edmCollectionType.FullName(); // But ODataLib currently doesn't support .FullName() for collections. As a workaround, we construct the // collection type name the hard way. string typeName = "Collection(" + elementType.FullName() + ")"; // ODataCollectionValue is only a V3 property, arrays inside Complex Types or Entity types are only supported in V3 // if a V1 or V2 Client requests a type that has a collection within it ODataLib will throw. ODataCollectionValue value = new ODataCollectionValue { Items = valueCollection, TypeName = typeName }; AddTypeNameAnnotationAsNeeded(value, writeContext.MetadataLevel); return value; }
public override void WriteObject(object graph, Type type, ODataMessageWriter messageWriter, ODataSerializerContext writeContext) { if (messageWriter == null) { throw new ArgumentNullException("messageWriter"); } if (writeContext == null) { throw new ArgumentNullException("writeContext"); } if (graph != null) { Uri[] uris = graph as Uri[]; if (uris == null) { throw new SerializationException("Cannot write the type"); } messageWriter.WriteEntityReferenceLinks(new ODataEntityReferenceLinks { Links = uris.Select(uri => new ODataEntityReferenceLink { Url = uri }) }); } }
public void Property_Items_IsInitialized() { ODataSerializerContext context = new ODataSerializerContext(); Assert.NotNull(context.Items); }
/// <summary> /// Writes the given object specified by the parameter graph as a whole using the given messageWriter and writeContext. /// </summary> /// <param name="graph">The object to be written</param> /// <param name="type">The type of the object to be written.</param> /// <param name="messageWriter">The <see cref="ODataMessageWriter"/> to be used for writing.</param> /// <param name="writeContext">The <see cref="ODataSerializerContext"/>.</param> public override void WriteObject(object graph, Type type, ODataMessageWriter messageWriter, ODataSerializerContext writeContext) { if (graph is EnumerableQuery <IEdmEntityObject> ) { var list = ((EnumerableQuery <IEdmEntityObject>)graph).AsIList(); var entityCollectionType = new EdmCollectionTypeReference((EdmCollectionType)((EdmEntitySet)writeContext.NavigationSource).Type); graph = new EdmEntityObjectCollection(entityCollectionType, list); } base.WriteObject(graph, type, messageWriter, writeContext); }
/// <summary> /// Create the <see cref="ODataFeed"/> to be written for the given feed instance. /// </summary> /// <param name="feedInstance">The instance representing the feed being written.</param> /// <param name="feedType">The EDM type of the feed being written.</param> /// <param name="writeContext">The serializer context.</param> /// <returns>The created <see cref="ODataFeed"/> object.</returns> public override ODataFeed CreateODataFeed(IEnumerable feedInstance, IEdmCollectionTypeReference feedType, ODataSerializerContext writeContext) { var feed = base.CreateODataFeed(feedInstance, feedType, writeContext); if (writeContext.Request.Properties.ContainsKey(Count)) { feed.Count = (int)writeContext.Request.Properties[Count]; } return(feed); }
public override ODataEnumValue CreateODataEnumValue(object graph, IEdmEnumTypeReference enumType, ODataSerializerContext writeContext) { ODataEnumValue result = base.CreateODataEnumValue(graph, enumType, writeContext); if (writeContext.Request.Headers.TryGetValues("Bit-Client-Type", out IEnumerable <string> values) && values.Any(v => string.Equals(v, "TS-Client", System.StringComparison.InvariantCultureIgnoreCase))) { if (!string.IsNullOrEmpty(result?.Value) && !string.IsNullOrEmpty(result.TypeName)) { // EnumKey >> "Namespace.EnumType'EnumKey'" result = new ODataEnumValue($"{result.TypeName}'{result.Value}'"); } } return(result); }
/// <summary> /// Initializes a new instance of the <see cref="EntityInstanceContext"/> class. /// </summary> /// <param name="serializerContext">The backing <see cref="ODataSerializerContext"/>.</param> /// <param name="entityType">The EDM entity type of this instance context.</param> /// <param name="entityInstance">The object representing the instance of this context.</param> public EntityInstanceContext(ODataSerializerContext serializerContext, IEdmEntityTypeReference entityType, object entityInstance) : this(serializerContext, entityType, AsEdmEntityObject(entityInstance, entityType)) { }
/// <summary> /// Initializes a new instance of the <see cref="EntityInstanceContext"/> class. /// </summary> public EntityInstanceContext() { SerializerContext = new ODataSerializerContext(); }
/// <summary> /// Writes the given <paramref name="graph"/> using the given <paramref name="writer"/>. /// </summary> /// <param name="writer">The <see cref="ODataCollectionWriter"/> to use.</param> /// <param name="graph">The collection to write.</param> /// <param name="collectionType">The EDM type of the collection.</param> /// <param name="writeContext">The serializer context.</param> public void WriteCollection(ODataCollectionWriter writer, object graph, IEdmTypeReference collectionType, ODataSerializerContext writeContext) { if (writer == null) { throw Error.ArgumentNull("writer"); } ODataCollectionValue collectionValue = CreateODataValue(graph, collectionType, writeContext) as ODataCollectionValue; writer.WriteStart(new ODataCollectionStart { Name = writeContext.RootElementName }); if (collectionValue != null) { foreach (object item in collectionValue.Items) { writer.WriteItem(item); } } writer.WriteEnd(); }
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext) { if (type == null) { throw Error.ArgumentNull("type"); } if (writeStream == null) { throw Error.ArgumentNull("writeStream"); } if (Request == null) { throw Error.NotSupported(SRResources.WriteToStreamAsyncMustHaveRequest); } HttpContentHeaders contentHeaders = content == null ? null : content.Headers; return(TaskHelpers.RunSynchronously(() => { // Get the format and version to use from the ODataServiceVersion content header or if not available use the // values configured for the specialized formatter instance. ODataVersion version; if (contentHeaders == null) { version = _defaultODataVersion; } else { version = GetODataVersion(contentHeaders, ODataFormatterConstants.ODataServiceVersion) ?? _defaultODataVersion; } // get the most appropriate serializer given that we support inheritance. type = value == null ? type : value.GetType(); ODataSerializer serializer = ODataSerializerProvider.GetODataPayloadSerializer(type); if (serializer == null) { throw Error.InvalidOperation(SRResources.TypeCannotBeSerialized, type.Name, typeof(ODataMediaTypeFormatter).Name); } UrlHelper urlHelper = Request.GetUrlHelper(); IEdmEntitySet targetEntitySet = null; ODataUriHelpers.TryGetEntitySetAndEntityType(Request.RequestUri, Model, out targetEntitySet); // serialize a response Uri baseAddress = new Uri(Request.RequestUri, Request.GetConfiguration().VirtualPathRoot); // TODO: Bug 467617: figure out the story for the operation name on the client side and server side. // This is clearly a workaround. We are assuming that the operation name is the last segment in the request uri // which works for most cases and fall back to the type name of the object being written. // We should rather use uri parser semantic tree to figure out the operation name from the request url. string operationName = ODataUriHelpers.GetOperationName(Request.RequestUri, baseAddress); operationName = operationName ?? type.Name; IODataResponseMessage responseMessage = new ODataMessageWrapper(writeStream); // TODO: Issue 483: http://aspnetwebstack.codeplex.com/workitem/483 // We need to set the MetadataDocumentUri when this property is added to ODataMessageWriterSettings as // part of the JSON Light work. // This is required so ODataLib can coerce AbsoluteUri's into RelativeUri's when appropriate in JSON Light. ODataMessageWriterSettings writerSettings = new ODataMessageWriterSettings() { BaseUri = baseAddress, Version = version, Indent = true, DisableMessageStreamDisposal = true }; if (contentHeaders != null && contentHeaders.ContentType != null) { writerSettings.SetContentType(contentHeaders.ContentType.ToString(), Encoding.UTF8.WebName); } using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, writerSettings, ODataDeserializerProvider.EdmModel)) { ODataSerializerContext writeContext = new ODataSerializerContext() { EntitySet = targetEntitySet, UrlHelper = urlHelper, ServiceOperationName = operationName, SkipExpensiveAvailabilityChecks = serializer.ODataPayloadKind == ODataPayloadKind.Feed, Request = Request }; serializer.WriteObject(value, messageWriter, writeContext); } })); }
/// <inheritdoc/> public override void WriteObject(object graph, Type type, ODataMessageWriter messageWriter, ODataSerializerContext writeContext) { if (messageWriter == null) { throw Error.ArgumentNull("messageWriter"); } if (writeContext == null) { throw Error.ArgumentNull("writeContext"); } if (writeContext.RootElementName == null) { throw Error.Argument("writeContext", SRResources.RootElementNameMissing, typeof(ODataSerializerContext).Name); } IEdmTypeReference edmType = writeContext.GetEdmType(graph, type); Contract.Assert(edmType != null); ODataProperty property = CreateProperty(graph, edmType, writeContext.RootElementName, writeContext); messageWriter.WriteProperty(property); }
private void WriteResponseBody(OutputFormatterWriteContext context) { HttpRequest request = context.HttpContext.Request; HttpResponse response = context.HttpContext.Response; IEdmModel model = request.ODataProperties().Model; if (model == null) { throw Error.InvalidOperation(SRResources.RequestMustHaveModel); } object value = context.Object; Type type = value.GetType(); ODataSerializer serializer = GetSerializer(type, value, model, context.HttpContext.RequestServices.GetService <ODataSerializerProvider>(), request); IUrlHelper urlHelper = context.HttpContext.UrlHelper(); ODataPath path = request.ODataProperties().Path; IEdmNavigationSource targetNavigationSource = path == null ? null : path.NavigationSource; string preferHeader = RequestPreferenceHelpers.GetRequestPreferHeader(request); string annotationFilter = null; if (!String.IsNullOrEmpty(preferHeader)) { ODataMessageWrapper messageWrapper = new ODataMessageWrapper(response.Body, response.Headers); messageWrapper.SetHeader(RequestPreferenceHelpers.PreferHeaderName, preferHeader); annotationFilter = messageWrapper.PreferHeader().AnnotationFilter; } IODataResponseMessage responseMessage = new ODataMessageWrapper(response.Body, response.Headers); if (annotationFilter != null) { responseMessage.PreferenceAppliedHeader().AnnotationFilter = annotationFilter; } Uri baseAddress = GetBaseAddress(request); ODataMessageWriterSettings writerSettings = new ODataMessageWriterSettings(_messageWriterSettings) { PayloadBaseUri = baseAddress, Version = ODataProperties.DefaultODataVersion, }; string metadataLink = urlHelper.CreateODataLink(new MetadataPathSegment()); if (metadataLink == null) { throw new SerializationException(SRResources.UnableToDetermineMetadataUrl); } writerSettings.ODataUri = new ODataUri { ServiceRoot = baseAddress, // TODO: 1604 Convert webapi.odata's ODataPath to ODL's ODataPath, or use ODL's ODataPath. SelectAndExpand = request.ODataProperties().SelectExpandClause, Path = (path == null || IsOperationPath(path)) ? null : path.ODLPath, }; using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, writerSettings, model)) { ODataSerializerContext writeContext = new ODataSerializerContext() { Request = request, RequestContext = request.HttpContext, Url = urlHelper, NavigationSource = targetNavigationSource, Model = model, RootElementName = GetRootElementName(path) ?? "root", SkipExpensiveAvailabilityChecks = serializer.ODataPayloadKind == ODataPayloadKind.Feed, Path = path, MetadataLevel = ODataMediaTypes.GetMetadataLevel(new MediaTypeHeaderValue(context.ContentType.Value)), SelectExpandClause = request.ODataProperties().SelectExpandClause }; serializer.WriteObjectAsync(value, type, messageWriter, writeContext); } }
private void WriteExpandedNavigationProperty( KeyValuePair<IEdmNavigationProperty, SelectExpandClause> navigationPropertyToExpand, EntityInstanceContext entityInstanceContext, ODataWriter writer) { Contract.Assert(entityInstanceContext != null); Contract.Assert(writer != null); IEdmNavigationProperty navigationProperty = navigationPropertyToExpand.Key; SelectExpandClause selectExpandClause = navigationPropertyToExpand.Value; object propertyValue = entityInstanceContext.GetPropertyValue(navigationProperty.Name); if (propertyValue == null) { if (navigationProperty.Type.IsCollection()) { // A navigation property whose Type attribute specifies a collection, the collection always exists, // it may just be empty. // If a collection of entities can be related, it is represented as a JSON array. An empty // collection of entities (one that contains no entities) is represented as an empty JSON array. writer.WriteStart(new ODataFeed()); } else { // If at most one entity can be related, the value is null if no entity is currently related. writer.WriteStart(entry: null); } writer.WriteEnd(); } else { // create the serializer context for the expanded item. ODataSerializerContext nestedWriteContext = new ODataSerializerContext(entityInstanceContext, selectExpandClause, navigationProperty); // write object. ODataEdmTypeSerializer serializer = SerializerProvider.GetEdmTypeSerializer(navigationProperty.Type); if (serializer == null) { throw new SerializationException( Error.Format(SRResources.TypeCannotBeSerialized, navigationProperty.Type.ToTraceString(), typeof(ODataOutputFormatter).Name)); } serializer.WriteObjectInline(propertyValue, navigationProperty.Type, writer, nestedWriteContext); } }
internal static async Task WriteToStreamAsync( Type type, object value, IEdmModel model, ODataVersion version, Uri baseAddress, MediaTypeHeaderValue contentType, HttpRequest request, IHeaderDictionary requestHeaders, IODataSerializerProvider serializerProvider) { if (model == null) { throw Error.InvalidOperation(SRResources.RequestMustHaveModel); } IODataSerializer serializer = GetSerializer(type, value, request, serializerProvider); ODataPath path = request.ODataFeature().Path; IEdmNavigationSource targetNavigationSource = GetTargetNavigationSource(path, model); HttpResponse response = request.HttpContext.Response; // serialize a response string preferHeader = RequestPreferenceHelpers.GetRequestPreferHeader(requestHeaders); string annotationFilter = null; if (!string.IsNullOrEmpty(preferHeader)) { ODataMessageWrapper messageWrapper = ODataMessageWrapperHelper.Create(response.Body, response.Headers); messageWrapper.SetHeader(RequestPreferenceHelpers.PreferHeaderName, preferHeader); annotationFilter = messageWrapper.PreferHeader().AnnotationFilter; } IODataResponseMessageAsync responseMessage = ODataMessageWrapperHelper.Create(new StreamWrapper(response.Body), response.Headers, request.GetRouteServices()); if (annotationFilter != null) { responseMessage.PreferenceAppliedHeader().AnnotationFilter = annotationFilter; } ODataMessageWriterSettings writerSettings = request.GetWriterSettings(); writerSettings.BaseUri = baseAddress; writerSettings.Version = version; writerSettings.Validations = writerSettings.Validations & ~ValidationKinds.ThrowOnUndeclaredPropertyForNonOpenType; string metadataLink = request.CreateODataLink(MetadataSegment.Instance); if (metadataLink == null) { throw new SerializationException(SRResources.UnableToDetermineMetadataUrl); } // Set this variable if the SelectExpandClause is different from the processed clause on the Query options SelectExpandClause selectExpandDifferentFromQueryOptions = null; ODataQueryOptions queryOptions = request.GetQueryOptions(); SelectExpandClause processedSelectExpandClause = request.ODataFeature().SelectExpandClause; if (queryOptions != null && queryOptions.SelectExpand != null) { if (queryOptions.SelectExpand.ProcessedSelectExpandClause != processedSelectExpandClause) { selectExpandDifferentFromQueryOptions = processedSelectExpandClause; } } else if (processedSelectExpandClause != null) { selectExpandDifferentFromQueryOptions = processedSelectExpandClause; } writerSettings.ODataUri = new ODataUri { ServiceRoot = baseAddress, // TODO: 1604 Convert webapi.odata's ODataPath to ODL's ODataPath, or use ODL's ODataPath. SelectAndExpand = processedSelectExpandClause, Apply = request.ODataFeature().ApplyClause, Path = path }; ODataMetadataLevel metadataLevel = ODataMetadataLevel.Minimal; if (contentType != null) { IEnumerable <KeyValuePair <string, string> > parameters = contentType.Parameters.Select(val => new KeyValuePair <string, string>(val.Name.ToString(), val.Value.ToString())); metadataLevel = ODataMediaTypes.GetMetadataLevel(contentType.MediaType.ToString(), parameters); } using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, writerSettings, model)) { ODataSerializerContext writeContext = BuildSerializerContext(request); writeContext.NavigationSource = targetNavigationSource; writeContext.Model = model; writeContext.RootElementName = GetRootElementName(path) ?? "root"; writeContext.SkipExpensiveAvailabilityChecks = serializer.ODataPayloadKind == ODataPayloadKind.ResourceSet; writeContext.Path = path; writeContext.MetadataLevel = metadataLevel; writeContext.QueryOptions = queryOptions; writeContext.SetComputedProperties(queryOptions?.Compute?.ComputeClause); //Set the SelectExpandClause on the context if it was explicitly specified. if (selectExpandDifferentFromQueryOptions != null) { writeContext.SelectExpandClause = selectExpandDifferentFromQueryOptions; } await serializer.WriteObjectAsync(value, type, messageWriter, writeContext).ConfigureAwait(false); } }
private static IEdmEntityType GetODataPathType(ODataSerializerContext serializerContext) { Contract.Assert(serializerContext != null); if (serializerContext.NavigationProperty != null) { // we are in an expanded navigation property. use the navigation source to figure out the // type. return serializerContext.NavigationSource.EntityType(); } else { // figure out the type from the path. IEdmType edmType = serializerContext.Path.EdmType; if (edmType.TypeKind == EdmTypeKind.Collection) { edmType = (edmType as IEdmCollectionType).ElementType.Definition; } return edmType as IEdmEntityType; } }
/// <summary> /// Initializes a new instance of the <see cref="ResourceContext"/> class. /// </summary> public ResourceContext() { SerializerContext = new ODataSerializerContext(); }
private IEdmEntityTypeReference GetEntityType(object graph, ODataSerializerContext writeContext) { Contract.Assert(graph != null); IEdmTypeReference edmType = writeContext.GetEdmType(graph, graph.GetType()); Contract.Assert(edmType != null); if (!edmType.IsEntity()) { throw new SerializationException( Error.Format(SRResources.CannotWriteType, GetType().Name, edmType.FullName())); } return edmType.AsEntity(); }
/// <summary> /// Initializes a new instance of the <see cref="ResourceContext"/> class. /// </summary> /// <param name="serializerContext">The backing <see cref="ODataSerializerContext"/>.</param> /// <param name="structuredType">The EDM structured type of this instance context.</param> /// <param name="resourceInstance">The object representing the instance of this context.</param> public ResourceContext(ODataSerializerContext serializerContext, IEdmStructuredTypeReference structuredType, object resourceInstance) : this(serializerContext, structuredType, AsEdmResourceObject(resourceInstance, structuredType, serializerContext.Model)) { }
/// <summary> /// Create the <see cref="ODataDeltaFeed"/> to be written for the given feed instance. /// </summary> /// <param name="feedInstance">The instance representing the feed being written.</param> /// <param name="feedType">The EDM type of the feed being written.</param> /// <param name="writeContext">The serializer context.</param> /// <returns>The created <see cref="ODataDeltaFeed"/> object.</returns> public virtual ODataDeltaFeed CreateODataDeltaFeed(IEnumerable feedInstance, IEdmCollectionTypeReference feedType, ODataSerializerContext writeContext) { ODataDeltaFeed feed = new ODataDeltaFeed(); if (writeContext.ExpandedEntity == null) { // If we have more OData format specific information apply it now, only if we are the root feed. PageResult odataFeedAnnotations = feedInstance as PageResult; if (odataFeedAnnotations != null) { feed.Count = odataFeedAnnotations.Count; feed.NextPageLink = odataFeedAnnotations.NextPageLink; } else if (writeContext.Request != null) { feed.NextPageLink = writeContext.Request.ODataProperties().NextLink; long? countValue = writeContext.Request.ODataProperties().TotalCount; if (countValue.HasValue) { feed.Count = countValue.Value; } } } else { // nested feed ITruncatedCollection truncatedCollection = feedInstance as ITruncatedCollection; if (truncatedCollection != null && truncatedCollection.IsTruncated) { feed.NextPageLink = GetNestedNextPageLink(writeContext, truncatedCollection.PageSize); } } return feed; }
/// <summary> /// Creates and returns an OData complex type value using the specified object graph, tpye, and context. /// </summary> /// <param name="graph">The object graph to create a complex value for.</param> /// <param name="complexType">The type of complex type.</param> /// <param name="writeContext">The current <see cref="ODataSerializerContext">serializer context</see>.</param> /// <returns>The created <see cref="ODataComplexValue">complex value</see>.</returns> public override ODataComplexValue CreateODataComplexValue(object graph, IEdmComplexTypeReference complexType, ODataSerializerContext writeContext) { var complexValue = base.CreateODataComplexValue(graph, complexType, writeContext); var context = new ODataSerializationFeatureContext(complexType, writeContext, ComplexTypeSerializer) { Instance = graph }; foreach (var feature in SerializationFeatures) { feature.Apply(complexValue, context); } return(complexValue); }
/// <summary> /// Writes the given deltaLink specified by the parameter graph as a part of an existing OData message using the given /// messageWriter and the writeContext. /// </summary> /// <param name="graph">The object to be written.</param> /// <param name="writer">The <see cref="ODataDeltaWriter" /> to be used for writing.</param> /// <param name="writeContext">The <see cref="ODataSerializerContext"/>.</param> public virtual void WriteDeltaLink(object graph, ODataDeltaWriter writer, ODataSerializerContext writeContext) { EdmDeltaLink edmDeltaLink = graph as EdmDeltaLink; if (edmDeltaLink == null) { throw new SerializationException(Error.Format(SRResources.CannotWriteType, GetType().Name, graph.GetType().FullName)); } ODataDeltaLink deltaLink = new ODataDeltaLink( edmDeltaLink.Source, edmDeltaLink.Target, edmDeltaLink.Relationship); if (deltaLink != null) { writer.WriteDeltaLink(deltaLink); } }
/// <summary> /// Returns the URI for NextPageLink /// </summary> /// <param name="baseUri">BaseUri for nextlink. It should be request URI for top level resource and navigation link for nested resource.</param> /// <param name="pageSize">Maximum number of records in the set of partial results for a resource.</param> /// <param name="instance">Instance based on which SkipToken value will be generated.</param> /// <param name="context">Serializer context</param> /// <returns>Returns the URI for NextPageLink. If a null object is passed for the instance, resorts to the default paging mechanism of using $skip and $top.</returns> public override Uri GenerateNextPageLink(Uri baseUri, int pageSize, Object instance, ODataSerializerContext context) { if (context == null) { return(null); } if (pageSize <= 0) { return(null); } Func <object, string> skipTokenGenerator = null; IList <OrderByNode> orderByNodes = null; ExpandedReferenceSelectItem expandedItem = context.CurrentSelectItem as ExpandedReferenceSelectItem; IEdmModel model = context.Model; DefaultQuerySettings settings = context.QueryContext.DefaultQuerySettings; if (settings.EnableSkipToken) { if (expandedItem != null) { // Handle Delta resource; currently not value based. if (TypedDelta.IsDeltaOfT(context.ExpandedResource.GetType())) { return(GetNextPageHelper.GetNextPageLink(baseUri, pageSize)); } if (expandedItem.OrderByOption != null) { orderByNodes = OrderByNode.CreateCollection(expandedItem.OrderByOption); } skipTokenGenerator = (obj) => { return(GenerateSkipTokenValue(obj, model, orderByNodes)); }; return(GetNextPageHelper.GetNextPageLink(baseUri, pageSize, instance, skipTokenGenerator)); } if (context.QueryOptions != null && context.QueryOptions.OrderBy != null) { orderByNodes = context.QueryOptions.OrderBy.OrderByNodes; } skipTokenGenerator = (obj) => { return(GenerateSkipTokenValue(obj, model, orderByNodes)); }; } return(GetNextPageHelper.GetNextPageLink(baseUri, pageSize, instance, skipTokenGenerator)); }
private void WriteToStream(Type type, object value, Stream writeStream, HttpContent content, HttpContentHeaders contentHeaders) { IEdmModel model = Request.ODataProperties().Model; if (model == null) { throw Error.InvalidOperation(SRResources.RequestMustHaveModel); } ODataSerializer serializer = GetSerializer(type, value, model, _serializerProvider); UrlHelper urlHelper = Request.GetUrlHelper() ?? new UrlHelper(Request); ODataPath path = Request.ODataProperties().Path; IEdmEntitySet targetEntitySet = path == null ? null : path.EntitySet; // serialize a response HttpConfiguration configuration = Request.GetConfiguration(); if (configuration == null) { throw Error.InvalidOperation(SRResources.RequestMustContainConfiguration); } IODataResponseMessage responseMessage = new ODataMessageWrapper(writeStream, content.Headers); ODataMessageWriterSettings writerSettings = new ODataMessageWriterSettings(MessageWriterSettings) { PayloadBaseUri = GetBaseAddress(Request), Version = _version, }; string metadataLink = urlHelper.CreateODataLink(new MetadataPathSegment()); if (metadataLink == null) { throw new SerializationException(SRResources.UnableToDetermineMetadataUrl); } string resourcePath = path != null?path.ToString() : String.Empty; Uri baseAddress = GetBaseAddress(Request); writerSettings.SetServiceDocumentUri( baseAddress, Request.ODataProperties().SelectExpandClause, resourcePath, isIndividualProperty: false); writerSettings.ODataUri = new ODataUri { ServiceRoot = baseAddress, // TODO: 1604 Convert webapi.odata's ODataPath to ODL's ODataPath, or use ODL's ODataPath. }; MediaTypeHeaderValue contentType = null; if (contentHeaders != null && contentHeaders.ContentType != null) { contentType = contentHeaders.ContentType; } using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, writerSettings, model)) { ODataSerializerContext writeContext = new ODataSerializerContext() { Request = Request, RequestContext = Request.GetRequestContext(), Url = urlHelper, EntitySet = targetEntitySet, Model = model, RootElementName = GetRootElementName(path) ?? "root", SkipExpensiveAvailabilityChecks = serializer.ODataPayloadKind == ODataPayloadKind.Feed, Path = path, MetadataLevel = ODataMediaTypes.GetMetadataLevel(contentType), SelectExpandClause = Request.ODataProperties().SelectExpandClause }; serializer.WriteObject(value, type, messageWriter, writeContext); } }
private void WriteToStream(Type type, object value, Stream writeStream, HttpContent content, HttpContentHeaders contentHeaders) { IEdmModel model = Request.GetEdmModel(); if (model == null) { throw Error.InvalidOperation(SRResources.RequestMustHaveModel); } ODataSerializer serializer = GetSerializer(type, value, model, _serializerProvider); UrlHelper urlHelper = Request.GetUrlHelper(); Contract.Assert(urlHelper != null); ODataPath path = Request.GetODataPath(); IEdmEntitySet targetEntitySet = path == null ? null : path.EntitySet; // serialize a response HttpConfiguration configuration = Request.GetConfiguration(); if (configuration == null) { throw Error.InvalidOperation(SRResources.RequestMustContainConfiguration); } IODataResponseMessage responseMessage = new ODataMessageWrapper(writeStream, content.Headers); ODataMessageWriterSettings writerSettings = new ODataMessageWriterSettings() { BaseUri = GetBaseAddress(Request), Version = _version, Indent = true, DisableMessageStreamDisposal = true, MessageQuotas = MessageWriterQuotas }; // The MetadataDocumentUri is never required for errors. Additionally, it sometimes won't be available // for errors, such as when routing itself fails. In that case, the route data property is not // available on the request, and due to a bug with HttpRoute.GetVirtualPath (bug #669) we won't be able // to generate a metadata link. if (serializer.ODataPayloadKind != ODataPayloadKind.Error) { string metadataLink = urlHelper.ODataLink(new MetadataPathSegment()); if (metadataLink == null) { throw new SerializationException(SRResources.UnableToDetermineMetadataUrl); } string selectClause = GetSelectClause(Request); writerSettings.SetMetadataDocumentUri(new Uri(metadataLink), selectClause); } MediaTypeHeaderValue contentType = null; if (contentHeaders != null && contentHeaders.ContentType != null) { contentType = contentHeaders.ContentType; } using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, writerSettings, model)) { ODataSerializerContext writeContext = new ODataSerializerContext() { Request = Request, Url = urlHelper, EntitySet = targetEntitySet, Model = model, RootElementName = GetRootElementName(path) ?? "root", SkipExpensiveAvailabilityChecks = serializer.ODataPayloadKind == ODataPayloadKind.Feed, Path = path, MetadataLevel = ODataMediaTypes.GetMetadataLevel(contentType), SelectExpandClause = Request.GetSelectExpandClause() }; serializer.WriteObject(value, messageWriter, writeContext); } }
/// <inheritdoc/> public override sealed ODataValue CreateODataValue(object graph, IEdmTypeReference expectedType, ODataSerializerContext writeContext) { if (graph == null) { throw new SerializationException(Error.Format(SRResources.NullCollectionsCannotBeSerialized)); } IEnumerable enumerable = graph as IEnumerable; if (enumerable == null) { throw Error.Argument("graph", SRResources.ArgumentMustBeOfType, typeof(IEnumerable).Name); } if (expectedType == null) { throw Error.ArgumentNull("expectedType"); } IEdmTypeReference elementType = GetElementType(expectedType); return CreateODataCollectionValue(enumerable, elementType, writeContext); }
private void WriteToStream(Type type, object value, Stream writeStream, HttpContent content, HttpContentHeaders contentHeaders) { IEdmModel model = Request.ODataProperties().Model; if (model == null) { throw Error.InvalidOperation(SRResources.RequestMustHaveModel); } ODataSerializer serializer = GetSerializer(type, value, model, _serializerProvider); UrlHelper urlHelper = Request.GetUrlHelper() ?? new UrlHelper(Request); ODataPath path = Request.ODataProperties().Path; IEdmNavigationSource targetNavigationSource = path == null ? null : path.NavigationSource; // serialize a response HttpConfiguration configuration = Request.GetConfiguration(); if (configuration == null) { throw Error.InvalidOperation(SRResources.RequestMustContainConfiguration); } string preferHeader = RequestPreferenceHelpers.GetRequestPreferHeader(Request); string annotationFilter = null; if (!String.IsNullOrEmpty(preferHeader)) { ODataMessageWrapper messageWrapper = new ODataMessageWrapper(writeStream, content.Headers); messageWrapper.SetHeader(RequestPreferenceHelpers.PreferHeaderName, preferHeader); annotationFilter = messageWrapper.PreferHeader().AnnotationFilter; } IODataResponseMessage responseMessage = new ODataMessageWrapper(writeStream, content.Headers); if (annotationFilter != null) { responseMessage.PreferenceAppliedHeader().AnnotationFilter = annotationFilter; } Uri baseAddress = GetBaseAddressInternal(Request); ODataMessageWriterSettings writerSettings = new ODataMessageWriterSettings(MessageWriterSettings) { PayloadBaseUri = baseAddress, Version = _version, }; string metadataLink = urlHelper.CreateODataLink(new MetadataPathSegment()); if (metadataLink == null) { throw new SerializationException(SRResources.UnableToDetermineMetadataUrl); } writerSettings.ODataUri = new ODataUri { ServiceRoot = baseAddress, // TODO: 1604 Convert webapi.odata's ODataPath to ODL's ODataPath, or use ODL's ODataPath. SelectAndExpand = Request.ODataProperties().SelectExpandClause, Apply = Request.ODataProperties().ApplyClause, Path = (path == null || IsOperationPath(path)) ? null : path.ODLPath, }; MediaTypeHeaderValue contentType = null; if (contentHeaders != null && contentHeaders.ContentType != null) { contentType = contentHeaders.ContentType; } using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, writerSettings, model)) { ODataSerializerContext writeContext = new ODataSerializerContext() { Request = Request, RequestContext = Request.GetRequestContext(), Url = urlHelper, NavigationSource = targetNavigationSource, Model = model, RootElementName = GetRootElementName(path) ?? "root", SkipExpensiveAvailabilityChecks = serializer.ODataPayloadKind == ODataPayloadKind.Feed, Path = path, MetadataLevel = ODataMediaTypes.GetMetadataLevel(contentType), SelectExpandClause = Request.ODataProperties().SelectExpandClause }; serializer.WriteObject(value, type, messageWriter, writeContext); } }
/// <inheritdoc/> public override void WriteObject(object graph, Type type, ODataMessageWriter messageWriter, ODataSerializerContext writeContext) { if (messageWriter == null) { throw Error.ArgumentNull("messageWriter"); } if (writeContext == null) { throw Error.ArgumentNull("writeContext"); } IEdmTypeReference collectionType = writeContext.GetEdmType(graph, type); Contract.Assert(collectionType != null); IEdmTypeReference elementType = GetElementType(collectionType); ODataCollectionWriter writer = messageWriter.CreateODataCollectionWriter(elementType); WriteCollection(writer, graph, collectionType.AsCollection(), writeContext); }
private void WriteDeltaEntry(object graph, ODataDeltaWriter writer, ODataSerializerContext writeContext) { Contract.Assert(writeContext != null); IEdmEntityTypeReference entityType = GetEntityType(graph, writeContext); EntityInstanceContext entityInstanceContext = new EntityInstanceContext(writeContext, entityType, graph); SelectExpandNode selectExpandNode = CreateSelectExpandNode(entityInstanceContext); if (selectExpandNode != null) { ODataEntry entry = CreateEntry(selectExpandNode, entityInstanceContext); if (entry != null) { writer.WriteStart(entry); //TODO: Need to add support to write Navigation Links using Delta Writer //https://github.com/OData/odata.net/issues/155 writer.WriteEnd(); } } }
/// <inheitdoc /> public override sealed ODataValue CreateODataValue(object graph, IEdmTypeReference expectedType, ODataSerializerContext writeContext) { if (expectedType == null) { throw Error.ArgumentNull("expectedType"); } if (!expectedType.IsComplex()) { throw new SerializationException( Error.Format(SRResources.CannotWriteType, GetType().Name, expectedType.FullName())); } return CreateODataComplexValue(graph, expectedType.AsComplex(), writeContext); }
private void WriteEntry(object graph, ODataWriter writer, ODataSerializerContext writeContext) { Contract.Assert(writeContext != null); IEdmEntityTypeReference entityType = GetEntityType(graph, writeContext); EntityInstanceContext entityInstanceContext = new EntityInstanceContext(writeContext, entityType, graph); SelectExpandNode selectExpandNode = CreateSelectExpandNode(entityInstanceContext); if (selectExpandNode != null) { ODataEntry entry = CreateEntry(selectExpandNode, entityInstanceContext); if (entry != null) { writer.WriteStart(entry); WriteNavigationLinks(selectExpandNode.SelectedNavigationProperties, entityInstanceContext, writer); WriteExpandedNavigationProperties(selectExpandNode.ExpandedNavigationProperties, entityInstanceContext, writer); writer.WriteEnd(); } } }
/// <summary> /// Creates an <see cref="ODataComplexValue"/> for the object represented by <paramref name="graph"/>. /// </summary> /// <param name="graph">The value of the <see cref="ODataComplexValue"/> to be created.</param> /// <param name="complexType">The EDM complex type of the object.</param> /// <param name="writeContext">The serializer context.</param> /// <returns>The created <see cref="ODataComplexValue"/>.</returns> public virtual ODataComplexValue CreateODataComplexValue(object graph, IEdmComplexTypeReference complexType, ODataSerializerContext writeContext) { if (writeContext == null) { throw Error.ArgumentNull("writeContext"); } if (graph == null || graph is NullEdmComplexObject) { return null; } IEdmComplexObject complexObject = graph as IEdmComplexObject ?? new TypedEdmComplexObject(graph, complexType, writeContext.Model); List<ODataProperty> propertyCollection = new List<ODataProperty>(); foreach (IEdmProperty property in complexType.ComplexDefinition().Properties()) { IEdmTypeReference propertyType = property.Type; ODataEdmTypeSerializer propertySerializer = SerializerProvider.GetEdmTypeSerializer(propertyType); if (propertySerializer == null) { throw Error.NotSupported(SRResources.TypeCannotBeSerialized, propertyType.FullName(), typeof(ODataOutputFormatter).Name); } object propertyValue; if (complexObject.TryGetPropertyValue(property.Name, out propertyValue)) { if (propertyType != null && propertyType.IsComplex()) { IEdmTypeReference actualType = writeContext.GetEdmType(propertyValue, propertyValue.GetType()); if (actualType != null && propertyType != actualType) { propertyType = actualType; } } propertyCollection.Add( propertySerializer.CreateProperty(propertyValue, propertyType, property.Name, writeContext)); } } // Try to add the dynamic properties if the complex type is open. if (complexType.ComplexDefinition().IsOpen) { List<ODataProperty> dynamicProperties = AppendDynamicProperties(complexObject, complexType, writeContext, propertyCollection, new string[0]); if (dynamicProperties != null) { propertyCollection.AddRange(dynamicProperties); } } string typeName = complexType.FullName(); ODataComplexValue value = new ODataComplexValue() { Properties = propertyCollection, TypeName = typeName }; AddTypeNameAnnotationAsNeeded(value, writeContext.MetadataLevel); return value; }
public override ODataPrimitiveValue CreateODataPrimitiveValue(object graph, IEdmPrimitiveTypeReference primitiveType, ODataSerializerContext writeContext) { ODataPrimitiveValue result = base.CreateODataPrimitiveValue(graph, primitiveType, writeContext); if (result?.Value is DateTimeOffset) { DateTimeOffset date = (DateTimeOffset)result.Value; IDependencyResolver dependencyResolver = writeContext.Request.GetOwinContext() .GetDependencyResolver(); ITimeZoneManager timeZoneManager = dependencyResolver.Resolve <ITimeZoneManager>(); result = new ODataPrimitiveValue(timeZoneManager.MapFromServerToClient(date)); } return(result); }