private HttpResponseMessage CreateQueryResponse(IQueryable query, IEdmType edmType, ETag etag) { var typeReference = GetTypeReference(edmType); BaseSingleResult singleResult = null; HttpResponseMessage response = null; if (typeReference.IsPrimitive()) { if (shouldReturnCount || shouldWriteRawValue) { var rawResult = new RawResult(query, typeReference); singleResult = rawResult; response = Request.CreateResponse(HttpStatusCode.OK, rawResult); } else { var primitiveResult = new PrimitiveResult(query, typeReference); singleResult = primitiveResult; response = Request.CreateResponse(HttpStatusCode.OK, primitiveResult); } } if (typeReference.IsComplex()) { var complexResult = new ComplexResult(query, typeReference); singleResult = complexResult; response = Request.CreateResponse(HttpStatusCode.OK, complexResult); } if (typeReference.IsEnum()) { if (shouldWriteRawValue) { var rawResult = new RawResult(query, typeReference); singleResult = rawResult; response = Request.CreateResponse(HttpStatusCode.OK, rawResult); } else { var enumResult = new EnumResult(query, typeReference); singleResult = enumResult; response = Request.CreateResponse(HttpStatusCode.OK, enumResult); } } if (singleResult != null) { if (singleResult.Result == null) { // Per specification, If the property is single-valued and has the null value, // the service responds with 204 No Content. return(Request.CreateResponse(HttpStatusCode.NoContent)); } return(response); } if (typeReference.IsCollection()) { var elementType = typeReference.AsCollection().ElementType(); if (elementType.IsPrimitive() || elementType.IsEnum()) { return(Request.CreateResponse(HttpStatusCode.OK, new NonResourceCollectionResult(query, typeReference))); } return(Request.CreateResponse(HttpStatusCode.OK, new ResourceSetResult(query, typeReference))); } var entityResult = query.SingleOrDefault(); if (entityResult == null) { return(Request.CreateResponse(HttpStatusCode.NoContent)); } // Check the ETag here if (etag != null) { // request with If-Match header, if match, then should return whole content // request with If-Match header, if not match, then should return 412 // request with If-None-Match header, if match, then should return 304 // request with If-None-Match header, if not match, then should return whole content etag.EntityType = query.ElementType; query = etag.ApplyTo(query); entityResult = query.SingleOrDefault(); if (entityResult == null && !etag.IsIfNoneMatch) { return(Request.CreateResponse(HttpStatusCode.PreconditionFailed)); } else if (entityResult == null) { return(Request.CreateResponse(HttpStatusCode.NotModified)); } } // Using reflection to create response for single entity so passed in parameter is not object type, // but will be type of real entity type, then EtagMessageHandler can be used to set ETAG header // when response is single entity. // There are three HttpRequestMessageExtensions class defined in different assembles // Fix by @xuzhg in PR #609. var assembly = System.Reflection.Assembly.GetAssembly(typeof(AcceptVerbsAttribute)); var type = assembly.GetType("System.Net.Http.HttpRequestMessageExtensions"); var genericMethod = type.GetMethods() .Where(m => m.Name == "CreateResponse" && m.GetParameters().Length == 3); var method = genericMethod.FirstOrDefault().MakeGenericMethod(query.ElementType); response = method.Invoke(null, new object[] { Request, HttpStatusCode.OK, entityResult }) as HttpResponseMessage; return(response); }