PageRenderTime 25ms CodeModel.GetById 15ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 0ms

/WCFWebApi/src/Microsoft.ApplicationServer.Http/Microsoft/ApplicationServer/Http/Dispatcher/QueryCompositionHandler.cs

#
C# | 123 lines | 90 code | 11 blank | 22 comment | 9 complexity | 6eff422466909ec52f18f275103e63c9 MD5 | raw file
  1// <copyright>
  2//   Copyright (c) Microsoft Corporation.  All rights reserved.
  3// </copyright>
  4
  5namespace Microsoft.ApplicationServer.Http.Dispatcher
  6{
  7    using System;
  8    using System.Collections;
  9    using System.Linq;
 10    using System.Net;
 11    using System.Net.Http;
 12    using System.Net.Http.Formatting;
 13    using System.Reflection;
 14    using Microsoft.ApplicationServer.Query;
 15    using Microsoft.Server.Common;
 16    using SR = Microsoft.ApplicationServer.Http.SR;
 17
 18    /// <summary>
 19    /// A <see cref="HttpOperationHandler"/> that composes a <see cref="IQueryable"/> with the result of the service operation.
 20    /// </summary>
 21    public class QueryCompositionHandler : HttpOperationHandler<HttpRequestMessage, HttpResponseMessage, HttpResponseMessage>
 22    {
 23        private Type returnResponseType;
 24        private ConstructorInfo returnResponseTypeConstructor;
 25
 26        /// <summary>
 27        /// Initialize a new instance of <see cref="QueryCompositionHandler"/> with the
 28        /// given <paramref name="returnType"/>.
 29        /// </summary>
 30        /// <param name="returnType">The return type of the service operation</param>
 31        public QueryCompositionHandler(Type returnType)
 32            : base("emptyDummy")
 33        {
 34            if (returnType == null)
 35            {
 36                throw Fx.Exception.ArgumentNull("returnType");
 37            }
 38
 39            returnType = HttpTypeHelper.GetHttpResponseOrContentInnerTypeOrNull(returnType) ?? returnType;
 40            if (!QueryTypeHelper.IsEnumerableInterfaceGenericTypeOrImplementation(returnType))
 41            {
 42                throw Fx.Exception.Argument("returnType", SR.RequiresQueryableType);
 43            }
 44
 45            Type queryElementType = QueryTypeHelper.GetEnumerableInterfaceInnerTypeOrNull(returnType);
 46            this.returnResponseType = HttpTypeHelper.HttpResponseMessageGenericType.MakeGenericType(QueryTypeHelper.EnumerableInterfaceGenericType.MakeGenericType(queryElementType));
 47            this.returnResponseTypeConstructor = this.returnResponseType.GetConstructor(
 48                new Type[]
 49                {
 50                    QueryTypeHelper.EnumerableInterfaceGenericType.MakeGenericType(queryElementType),
 51                    typeof(HttpStatusCode),
 52                    typeof(MediaTypeFormatterCollection)
 53                });
 54        }
 55
 56        /// <summary>
 57        /// Composes the service query with the result of the service operation and returns a new <see cref="HttpResponseMessage"/>, overriding the previous result.
 58        /// </summary>
 59        /// <param name="request">The original <see cref="HttpRequestMessage"/> for this request.</param>
 60        /// <param name="response">The <see cref="HttpResponseMessage"/> produced by the <see cref="ResponseContentHandler"/> from the service operation result.</param>
 61        /// <returns>
 62        /// The <see cref="HttpResponseMessage"/> resulting from the composition of the <paramref name="response"/> and
 63        /// the serviceQuery Property set on the <see cref="HttpRequestMessage"/>.
 64        /// </returns>
 65        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", Justification = "Better Intellisense experience for developers.")]
 66        protected override HttpResponseMessage OnHandle(HttpRequestMessage request, HttpResponseMessage response)
 67        {
 68            if (request == null)
 69            {
 70                throw Fx.Exception.ArgumentNull("request");
 71            }
 72
 73            IQueryable query = null;
 74            if (request.Properties.ContainsKey(QueryDeserializationHandler.QueryPropertyName))
 75            {
 76                query = request.Properties[QueryDeserializationHandler.QueryPropertyName] as IQueryable;
 77            }
 78            else
 79            {
 80                // No Query to compose, return unmodified HttpResponseMessage
 81                return response;
 82            }
 83
 84            IQueryable source = null;
 85            if (response != null && QueryTypeHelper.IsEnumerableInterfaceGenericTypeOrImplementation(HttpTypeHelper.GetHttpResponseInnerTypeOrNull(response.GetType())))
 86            {
 87                source = ((IEnumerable)((ObjectContent)response.Content).ReadAsAsync().Result).AsQueryable();
 88            }
 89            else
 90            {
 91                // No Query to compose, return unmodified HttpResponseMessage
 92                return response;
 93            }
 94
 95            try
 96            {
 97                IEnumerable composedQuery = QueryComposer.Compose(source, query);
 98
 99                HttpResponseMessage newResponse = (HttpResponseMessage)this.returnResponseTypeConstructor.Invoke(
100                    new object[]
101                    {
102                        composedQuery,
103                        response.StatusCode,
104                        ((ObjectContent)response.Content).Formatters
105                    });
106                newResponse.Headers.Clear();
107                response.Headers.CopyTo(newResponse.Headers);
108                response.Content.Headers.CopyTo(newResponse.Content.Headers);
109                newResponse.ReasonPhrase = response.ReasonPhrase;
110                newResponse.RequestMessage = response.RequestMessage;
111                newResponse.Version = response.Version;
112                ((ObjectContent)newResponse.Content).Headers.Clear();
113                ((ObjectContent)response.Content).Headers.CopyTo(((ObjectContent)newResponse.Content).Headers);
114
115                return newResponse;
116            }
117            catch (ParseException)
118            {
119                throw new HttpResponseException(SR.QueryCompositionFailed);
120            }
121        }
122    }
123}