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