public override void Process(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage) { object result; if (this.HttpMethod == HttpMethod.GET) { // we cannot invoke same action request multiple times, so only Functions are allowed to do the server-driven paging this.QueryContext.InitializeServerDrivenPaging(this.PreferenceContext); result = this.ProcessFunction(); if (this.PreferenceContext.MaxPageSize.HasValue) { responseMessage.AddPreferenceApplied(string.Format("{0}={1}", ServiceConstants.Preference_MaxPageSize, this.QueryContext.appliedPageSize.Value)); } } else { // TODO: currently ETag feature does not support action operation result = this.ProcessAction(requestMessage); } if (result == 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; } using (var messageWriter = this.CreateMessageWriter(responseMessage)) { if (this.QueryContext.Target.TypeKind == EdmTypeKind.None || this.QueryContext.Target.TypeKind == EdmTypeKind.EntityReference || this.QueryContext.Target.ElementTypeKind == EdmTypeKind.EntityReference) { throw Utility.BuildException(HttpStatusCode.NotImplemented, "Unsupported return type in operation.", null); } else if (this.QueryContext.Target.TypeKind == EdmTypeKind.Entity || this.QueryContext.Target.ElementTypeKind == EdmTypeKind.Entity || this.QueryContext.Target.TypeKind == EdmTypeKind.Complex || this.QueryContext.Target.ElementTypeKind == EdmTypeKind.Complex) { ODataWriter resultWriter; IEdmNavigationSource entitySource = this.QueryContext.OperationResultSource ?? this.QueryContext.Target.NavigationSource; if (this.QueryContext.Target.TypeKind == EdmTypeKind.Collection) { IEdmEntitySetBase entitySet = (IEdmEntitySetBase)entitySource; resultWriter = messageWriter.CreateODataResourceSetWriter(entitySet, (IEdmStructuredType)this.QueryContext.Target.ElementType); ResponseWriter.WriteFeed(resultWriter, (IEdmStructuredType)this.QueryContext.Target.ElementType, result as IEnumerable, entitySet, ODataVersion.V4, this.QueryContext.QuerySelectExpandClause, this.QueryContext.TotalCount, null, this.QueryContext.NextLink, this.RequestHeaders); } else { if (this.HttpMethod == HttpMethod.GET) { var currentETag = Utility.GetETagValue(result); // 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); } } resultWriter = messageWriter.CreateODataResourceWriter(entitySource, (IEdmStructuredType)this.QueryContext.Target.Type); ResponseWriter.WriteEntry(resultWriter, result, entitySource, ODataVersion.V4, this.QueryContext.QuerySelectExpandClause, this.RequestHeaders); } } else { ODataProperty property = new ODataProperty() { Name = "value", Value = ODataObjectModelConverter.CreateODataValue(result) }; messageWriter.WriteProperty(property); } } }
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); } } }