Move from WCF Data Services to Web API – Part 3

See Part 1 and Part 2.  I know in Part 2 I said I was going to look at ExpressionTrees and limit down to a single entity but I wanted to fix the Content Negotiation and add the service document.  Both turned out to be simple, once I discovered the Media Type you pass into the ODataMediaTypeFormatter doesn’t do anything.

First I created another method to return back the correct MediaTypeFormatter

        private MediaTypeFormatter GetFormatter(Type objType)
        {
            var conneg = Configuration.Services.GetContentNegotiator();
            var result = conneg.Negotiate(objType, Request, Configuration.Formatters);
            return result.Formatter;
        }

Then changed GenerateMetadataResponse to this

        protected HttpResponseMessage GenerateMetadataResponse()
        {
            var odataMediaTypeFormatter = GetFormatter(typeof (IEdmModel));
            var formatter = odataMediaTypeFormatter.GetPerRequestFormatterInstance(typeof (IEdmModel), Request,
                                                                                   null);
            var response = Request.CreateResponse();
            response.Content = new ObjectContent(typeof(IEdmModel), GetMetadata(), formatter);
            return response;
        }

Now it’s not hard coded to XML but still returns XML.  What’s still missing if you just say you want JSON it doesn’t error like WCF Data Services did it will just return XML.  I think it should error (add to the list)

This is the bottom part of QueryEntitySet

                var response = Request.CreateResponse();
                var resultType = typeof(IEnumerable<>).MakeGenericType(query.ElementType);
                var odataMediaTypeFormatter = GetFormatter(resultType);
                var formatter = odataMediaTypeFormatter.GetPerRequestFormatterInstance(typeof(IEdmCollectionType), Request, null);
                response.Content = new ObjectContent(resultType, query, formatter);

                return response;

Pretty straight forward.   I also created the Service Document for the OData.  That turned out to be simple.

        private HttpResponseMessage GenerateServiceDocument()
        {
            var response = Request.CreateResponse();
            var odataMediaTypeFormatter = GetFormatter(typeof(ODataWorkspace));
            var formatter = odataMediaTypeFormatter.GetPerRequestFormatterInstance(typeof(ODataWorkspace), Request, null);
            response.Content = new ObjectContent(typeof(ODataWorkspace), GetServiceDocument(), formatter);
            return response;
        }

This is ProcessRequest now

        protected virtual HttpResponseMessage ProcessRequest()
        {
            var pathHandler = Request.GetODataPathHandler();
            var metadata = GetMetadata();
            var path = pathHandler.Parse(metadata, GetODataPath());
            Request.SetODataPath(path);
            Request.SetODataRouteName("OData");
            if (path.Segments.Count == 0)
            {
                // Requested service document
                return GenerateServiceDocument();
            }

            if (path.Segments.Any(s => s.SegmentKind == ODataSegmentKinds.Metadata))
            {
                // Requested metadata
                return GenerateMetadataResponse();
            }

            var collectionType = path.EdmType as IEdmCollectionType;
            if (collectionType != null)
            {
                // Requested entity collection
                return QueryEntitySet(collectionType);
            }

            return new HttpResponseMessage(HttpStatusCode.NotImplemented);
        }

Now in Part 4 I’ll get to working on the ExpressionTrees.

Tags: , ,

Wednesday, April 16th, 2014 OData