PageRenderTime 42ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/TechEdWebApiDemo/App_Start/ODataExtensions.cs

https://github.com/garchibald/TechEdWebApiDemo
C# | 145 lines | 108 code | 21 blank | 16 comment | 25 complexity | e66bf34600ccc94f79effe9d633d548c MD5 | raw file
  1. //
  2. // Grant Archibald (c) 2012
  3. //
  4. // See Licence.txt
  5. //
  6. using System;
  7. using System.Collections.Specialized;
  8. using System.Linq;
  9. using System.Net.Http;
  10. using System.Text;
  11. using System.Web.Http.OData;
  12. using System.Web.Http.OData.Builder;
  13. using System.Web.Http.OData.Query;
  14. using Microsoft.Data.Edm;
  15. namespace OData.Framework
  16. {
  17. public static class ODataExtensions
  18. {
  19. /// <summary>
  20. /// Parse the <see cref="Request"/> to map non standard OData queries into OData queries
  21. /// </summary>
  22. /// <remarks>Examples of non standard query</remarks>
  23. /// <remarks>http://example.com/movies?rating=G,PG</remarks>
  24. /// <remarks>http://example.com/movies?id=1,2,3</remarks>
  25. /// <remarks>http://example.com/movies?released=2010-11-01</remarks>
  26. /// <typeparam name="T">The type that the query relates to</typeparam>
  27. /// <param name="query">The query to parse</param>
  28. /// <param name="request">The request to parse</param>
  29. /// <returns>The parse query</returns>
  30. public static ODataQueryOptions Parse<T>(
  31. this ODataQueryOptions query, HttpRequestMessage request) where T : class
  32. {
  33. var modelBuilder = new ODataConventionModelBuilder();
  34. modelBuilder.EntitySet<T>(typeof (T).Name + "s");
  35. var model = modelBuilder.GetEdmModel();
  36. return
  37. new ODataQueryOptions(
  38. new ODataQueryContext(model, typeof (T)), MapQueryRequest(model, request));
  39. }
  40. private static HttpRequestMessage MapQueryRequest(IEdmModel model,
  41. HttpRequestMessage request)
  42. {
  43. var uri = string.Format("{0}://{1}/{2}?{3}", request.RequestUri.Scheme
  44. ,
  45. request.RequestUri.GetComponents(UriComponents.HostAndPort,
  46. UriFormat.SafeUnescaped)
  47. ,
  48. request.RequestUri.GetComponents(UriComponents.Path,
  49. UriFormat.SafeUnescaped)
  50. , ParseQuery(request.RequestUri.ParseQueryString(), model));
  51. var mappedUri = new Uri(uri);
  52. var mappedRequest = new HttpRequestMessage {RequestUri = mappedUri};
  53. return mappedRequest;
  54. }
  55. private static string ParseQuery(NameValueCollection queryNames,
  56. IEdmModel model)
  57. {
  58. var query = new StringBuilder();
  59. foreach (var key in queryNames.AllKeys)
  60. {
  61. if (query.Length > 0)
  62. query.Append("&");
  63. if (key.StartsWith("$"))
  64. {
  65. query.Append(key);
  66. query.Append("=");
  67. query.Append(queryNames[key]);
  68. }
  69. else
  70. {
  71. if (!string.IsNullOrEmpty(queryNames[key]))
  72. {
  73. query.Append("$filter=");
  74. query.Append("(");
  75. for (int index = 0;
  76. index <
  77. queryNames[key].Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).Length;
  78. index++)
  79. {
  80. if (index > 0)
  81. {
  82. query.Append(" or ");
  83. }
  84. var keyPart =
  85. queryNames[key].Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries)[index];
  86. var prop = FindEdmProperty(model, key);
  87. query.Append(prop != null ? prop.Name : key);
  88. query.Append(" eq ");
  89. if (prop == null || prop.Type.IsString())
  90. query.Append("'");
  91. if (prop == null || prop.Type.IsDateTime())
  92. query.Append("datetime'");
  93. query.Append(keyPart);
  94. if (prop == null || prop.Type.IsDateTime() || prop.Type.IsString())
  95. query.Append("'");
  96. }
  97. query.Append(")");
  98. }
  99. }
  100. }
  101. return query.ToString();
  102. }
  103. private static IEdmProperty FindEdmProperty(IEdmModel model,
  104. string keyPart)
  105. {
  106. if (model == null)
  107. return null;
  108. if (model.EntityContainers() == null)
  109. return null;
  110. if (!model.EntityContainers().Any())
  111. return null;
  112. var container = model.EntityContainers().First();
  113. if (!container.EntitySets().Any())
  114. return null;
  115. var entity = container.EntitySets().First();
  116. if (entity.ElementType == null)
  117. return null;
  118. var elementType = entity.ElementType;
  119. return
  120. elementType.Properties().FirstOrDefault(
  121. p => string.Compare(p.Name, keyPart, StringComparison.OrdinalIgnoreCase) == 0);
  122. }
  123. }
  124. }