PageRenderTime 55ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/test/System.Web.Http.OData.Test/OData/Formatter/InheritanceTests.cs

http://aspnetwebstack.codeplex.com
C# | 419 lines | 344 code | 74 blank | 1 comment | 3 complexity | f73d7538837dacb427e5c97b16b60b18 MD5 | raw file
  1. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Net.Http;
  6. using System.Net.Http.Headers;
  7. using System.Web.Http.OData.Builder;
  8. using System.Web.Http.OData.Builder.TestModels;
  9. using System.Web.Http.OData.Formatter.Deserialization;
  10. using System.Web.Http.OData.Routing;
  11. using System.Xml.Linq;
  12. using Microsoft.Data.Edm;
  13. using Microsoft.Data.Edm.Library;
  14. using Microsoft.Data.OData;
  15. using Microsoft.TestCommon;
  16. using Newtonsoft.Json.Linq;
  17. namespace System.Web.Http.OData.Formatter
  18. {
  19. public class InheritanceTests
  20. {
  21. HttpServer _server;
  22. HttpClient _client;
  23. IEdmModel _model;
  24. public InheritanceTests()
  25. {
  26. HttpConfiguration configuration = new HttpConfiguration();
  27. _model = GetEdmModel();
  28. IEnumerable<ODataMediaTypeFormatter> formatters = ODataMediaTypeFormatters.Create();
  29. configuration.Formatters.Clear();
  30. configuration.Formatters.AddRange(formatters);
  31. configuration.Routes.MapHttpRoute("default", "{action}", new { Controller = "Inheritance" });
  32. configuration.Routes.MapFakeODataRoute();
  33. _server = new HttpServer(configuration);
  34. _client = new HttpClient(_server);
  35. }
  36. [Fact]
  37. public void Action_Can_Return_Entity_In_Inheritance()
  38. {
  39. HttpResponseMessage response = _client.SendAsync(GetODataRequest("http://localhost/GetMotorcycleAsVehicle")).Result;
  40. response.EnsureSuccessStatusCode();
  41. dynamic result = JObject.Parse(response.Content.ReadAsStringAsync().Result);
  42. result = result.d;
  43. ValidateMotorcycle(result);
  44. }
  45. [Fact]
  46. public void Action_Can_Return_Car_As_vehicle()
  47. {
  48. HttpResponseMessage response = _client.SendAsync(GetODataRequest("http://localhost/GetCarAsVehicle")).Result;
  49. response.EnsureSuccessStatusCode();
  50. dynamic result = JObject.Parse(response.Content.ReadAsStringAsync().Result);
  51. result = result.d;
  52. ValidateCar(result);
  53. }
  54. [Fact]
  55. public void Action_Can_Return_ClrType_NotInModel()
  56. {
  57. HttpResponseMessage response = _client.SendAsync(GetODataRequest("http://localhost/GetSportBikeAsVehicle")).Result;
  58. response.EnsureSuccessStatusCode();
  59. dynamic result = JObject.Parse(response.Content.ReadAsStringAsync().Result);
  60. result = result.d;
  61. ValidateSportbike(result);
  62. }
  63. [Fact]
  64. public void Action_Can_Return_CollectionOfEntities()
  65. {
  66. HttpResponseMessage response = _client.SendAsync(GetODataRequest("http://localhost/GetVehicles")).Result;
  67. response.EnsureSuccessStatusCode();
  68. dynamic result = JObject.Parse(response.Content.ReadAsStringAsync().Result);
  69. result = result.d;
  70. ValidateMotorcycle(result.results[0]);
  71. ValidateCar(result.results[1]);
  72. ValidateSportbike(result.results[2]);
  73. }
  74. [Fact]
  75. public void Action_Can_Take_Entity_In_Inheritance()
  76. {
  77. Stream body = GetResponseStream("http://localhost/GetMotorcycleAsVehicle", "application/atom+xml");
  78. HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/PostMotorcycle_When_Expecting_Motorcycle");
  79. request.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json;odata=verbose"));
  80. AddRequestInfo(request);
  81. request.Content = new StreamContent(body);
  82. request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/atom+xml");
  83. HttpResponseMessage response = _client.SendAsync(request).Result;
  84. response.EnsureSuccessStatusCode();
  85. dynamic result = JObject.Parse(response.Content.ReadAsStringAsync().Result);
  86. result = result.d;
  87. ValidateMotorcycle(result);
  88. }
  89. [Fact]
  90. public void Can_Patch_Entity_In_Inheritance()
  91. {
  92. HttpRequestMessage request = new HttpRequestMessage(new HttpMethod("PATCH"), "http://localhost/PatchMotorcycle_When_Expecting_Motorcycle");
  93. request.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json;odata=verbose"));
  94. AddRequestInfo(request);
  95. request.Content = new StringContent("{ 'CanDoAWheelie' : false }");
  96. request.Content.Headers.ContentType = MediaTypeWithQualityHeaderValue.Parse("application/json;odata=verbose");
  97. HttpResponseMessage response = _client.SendAsync(request).Result;
  98. response.EnsureSuccessStatusCode();
  99. dynamic result = JObject.Parse(response.Content.ReadAsStringAsync().Result);
  100. result = result.d;
  101. Assert.False((bool)result.CanDoAWheelie);
  102. }
  103. [Fact]
  104. public void Can_Post_DerivedType_To_Action_Expecting_BaseType()
  105. {
  106. Stream body = GetResponseStream("http://localhost/GetMotorcycleAsVehicle", "application/atom+xml");
  107. HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/PostMotorcycle_When_Expecting_Vehicle");
  108. request.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json;odata=verbose"));
  109. AddRequestInfo(request);
  110. request.Content = new StreamContent(body);
  111. request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/atom+xml");
  112. HttpResponseMessage response = _client.SendAsync(request).Result;
  113. response.EnsureSuccessStatusCode();
  114. dynamic result = JObject.Parse(response.Content.ReadAsStringAsync().Result);
  115. result = result.d;
  116. ValidateMotorcycle(result);
  117. }
  118. [Fact]
  119. public void Can_Post_DerivedType_To_Action_Expecting_BaseType_ForJsonLight()
  120. {
  121. Stream body = GetResponseStream("http://localhost/GetMotorcycleAsVehicle", "application/json;odata=minimalmetadata");
  122. HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/PostMotorcycle_When_Expecting_Vehicle");
  123. request.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json;odata=minimalmetadata"));
  124. AddRequestInfo(request);
  125. request.Content = new StreamContent(body);
  126. request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json;odata=minimalmetadata");
  127. HttpResponseMessage response = _client.SendAsync(request).Result;
  128. response.EnsureSuccessStatusCode();
  129. dynamic result = JObject.Parse(response.Content.ReadAsStringAsync().Result);
  130. ValidateMotorcycle(result, true);
  131. }
  132. [Fact]
  133. public void Can_Patch_DerivedType_To_Action_Expecting_BaseType()
  134. {
  135. HttpRequestMessage request = new HttpRequestMessage(new HttpMethod("PATCH"), "http://localhost/PatchMotorcycle_When_Expecting_Vehicle");
  136. request.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json;odata=verbose"));
  137. AddRequestInfo(request);
  138. request.Content = new StringContent("{ '__metadata': { 'type': 'System.Web.Http.OData.Builder.TestModels.Motorcycle' }, 'CanDoAWheelie' : false }");
  139. request.Content.Headers.ContentType = MediaTypeWithQualityHeaderValue.Parse("application/json;odata=verbose");
  140. HttpResponseMessage response = _client.SendAsync(request).Result;
  141. response.EnsureSuccessStatusCode();
  142. dynamic result = JObject.Parse(response.Content.ReadAsStringAsync().Result);
  143. result = result.d;
  144. Assert.False((bool)result.CanDoAWheelie);
  145. }
  146. [Fact]
  147. public void Can_Patch_DerivedType_To_Action_Expecting_BaseType_ForJsonLight()
  148. {
  149. HttpRequestMessage request = new HttpRequestMessage(new HttpMethod("PATCH"), "http://localhost/PatchMotorcycle_When_Expecting_Vehicle");
  150. request.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json;odata=minimalmetadata"));
  151. AddRequestInfo(request);
  152. request.Content = new StringContent("{ 'odata.type': 'System.Web.Http.OData.Builder.TestModels.Motorcycle', 'CanDoAWheelie' : false }");
  153. request.Content.Headers.ContentType = MediaTypeWithQualityHeaderValue.Parse("application/json;odata=minimalmetadata");
  154. HttpResponseMessage response = _client.SendAsync(request).Result;
  155. response.EnsureSuccessStatusCode();
  156. dynamic result = JObject.Parse(response.Content.ReadAsStringAsync().Result);
  157. Assert.False((bool)result.CanDoAWheelie);
  158. }
  159. [Fact]
  160. public void Posting_NonDerivedType_To_Action_Expecting_BaseType_Throws()
  161. {
  162. StringContent content = new StringContent("{ '__metadata' : { 'type' : 'System.Web.Http.OData.Builder.TestModels.Motorcycle' } }");
  163. content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json;odata=verbose");
  164. IODataRequestMessage oDataRequest = new ODataMessageWrapper(content.ReadAsStreamAsync().Result, content.Headers);
  165. ODataMessageReader reader = new ODataMessageReader(oDataRequest, new ODataMessageReaderSettings(), _model);
  166. ODataDeserializerProvider deserializerProvider = new DefaultODataDeserializerProvider();
  167. IEdmEntityTypeReference _motorcycle =
  168. new EdmEntityTypeReference(_model.SchemaElements.OfType<IEdmEntityType>().Single(t => t.Name == "Car"), isNullable: false);
  169. ODataDeserializerContext context = new ODataDeserializerContext();
  170. context.Path = new ODataPath(new ActionPathSegment(_model.EntityContainers().Single().FunctionImports().Single(f => f.Name == "PostMotorcycle_When_Expecting_Car")));
  171. Assert.Throws<ODataException>(
  172. () => new ODataEntityDeserializer(_motorcycle, deserializerProvider).Read(reader, context),
  173. "An entry with type 'System.Web.Http.OData.Builder.TestModels.Motorcycle' was found, " +
  174. "but it is not assignable to the expected type 'System.Web.Http.OData.Builder.TestModels.Car'. " +
  175. "The type specified in the entry must be equal to either the expected type or a derived type.");
  176. }
  177. private Stream GetResponseStream(string uri, string contentType)
  178. {
  179. HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri);
  180. request.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse(contentType));
  181. AddRequestInfo(request);
  182. HttpResponseMessage response = _client.SendAsync(request).Result;
  183. response.EnsureSuccessStatusCode();
  184. Stream stream = response.Content.ReadAsStreamAsync().Result;
  185. return stream;
  186. }
  187. private static void ValidateMotorcycle(dynamic result)
  188. {
  189. ValidateMotorcycle(result, false);
  190. }
  191. private static void ValidateMotorcycle(dynamic result, bool jsonLight)
  192. {
  193. if (jsonLight)
  194. {
  195. Assert.Equal("System.Web.Http.OData.Builder.TestModels.Motorcycle", (string)result["odata.type"]);
  196. }
  197. else
  198. {
  199. Assert.Equal("System.Web.Http.OData.Builder.TestModels.Motorcycle", (string)result.__metadata.type);
  200. }
  201. Assert.Equal("sample motorcycle", (string)result.Name);
  202. Assert.Equal("2009", (string)result.Model);
  203. Assert.Equal(2, (int)result.WheelCount);
  204. Assert.Equal(true, (bool)result.CanDoAWheelie);
  205. }
  206. private static void ValidateCar(dynamic result)
  207. {
  208. Assert.Equal("System.Web.Http.OData.Builder.TestModels.Car", (string)result.__metadata.type);
  209. Assert.Equal("sample car", (string)result.Name);
  210. Assert.Equal("2009", (string)result.Model);
  211. Assert.Equal(4, (int)result.WheelCount);
  212. Assert.Equal(5, (int)result.SeatingCapacity);
  213. }
  214. private static void ValidateSportbike(dynamic result)
  215. {
  216. Assert.Equal("System.Web.Http.OData.Builder.TestModels.Motorcycle", (string)result.__metadata.type);
  217. Assert.Equal("sample sportsbike", (string)result.Name);
  218. Assert.Equal("2009", (string)result.Model);
  219. Assert.Equal(2, (int)result.WheelCount);
  220. Assert.Equal(true, (bool)result.CanDoAWheelie);
  221. Assert.Null(result.SportBikeProperty_NotVisible);
  222. }
  223. private HttpRequestMessage GetODataRequest(string uri)
  224. {
  225. HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri);
  226. request.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json;odata=verbose"));
  227. AddRequestInfo(request);
  228. return request;
  229. }
  230. private void AddRequestInfo(HttpRequestMessage request)
  231. {
  232. request.SetODataPath(new DefaultODataPathHandler().Parse(_model, GetODataPath(
  233. request.RequestUri.AbsoluteUri)));
  234. request.SetEdmModel(_model);
  235. request.SetFakeODataRouteName();
  236. }
  237. private static IEdmModel GetEdmModel()
  238. {
  239. ODataModelBuilder builder = new ODataModelBuilder();
  240. builder
  241. .Entity<Vehicle>()
  242. .HasKey(v => v.Name)
  243. .HasKey(v => v.Model)
  244. .Property(v => v.WheelCount);
  245. builder
  246. .Entity<Motorcycle>()
  247. .DerivesFrom<Vehicle>()
  248. .Property(m => m.CanDoAWheelie);
  249. builder
  250. .Entity<Car>()
  251. .DerivesFrom<Vehicle>()
  252. .Property(c => c.SeatingCapacity);
  253. builder.EntitySet<Vehicle>("vehicles").HasIdLink(
  254. (v) => "http://localhost/vehicles/" + v.EntityInstance.Name, followsConventions: false);
  255. builder.EntitySet<Motorcycle>("motorcycles").HasIdLink(
  256. (m) => "http://localhost/motorcycles/" + m.EntityInstance.Name, followsConventions: false);
  257. builder.EntitySet<Car>("cars");
  258. builder
  259. .Action("GetCarAsVehicle")
  260. .ReturnsFromEntitySet<Vehicle>("vehicles");
  261. builder
  262. .Action("GetMotorcycleAsVehicle")
  263. .ReturnsFromEntitySet<Vehicle>("vehicles");
  264. builder
  265. .Action("GetSportBikeAsVehicle")
  266. .ReturnsFromEntitySet<Vehicle>("vehicles");
  267. builder
  268. .Action("GetVehicles")
  269. .ReturnsFromEntitySet<Vehicle>("vehicles");
  270. builder
  271. .Action("PatchMotorcycle_When_Expecting_Motorcycle")
  272. .ReturnsFromEntitySet<Motorcycle>("motorcycles");
  273. builder
  274. .Action("PostMotorcycle_When_Expecting_Motorcycle")
  275. .ReturnsFromEntitySet<Motorcycle>("motorcycles");
  276. builder
  277. .Action("PatchMotorcycle_When_Expecting_Vehicle")
  278. .ReturnsFromEntitySet<Vehicle>("vehicles");
  279. builder
  280. .Action("PostMotorcycle_When_Expecting_Vehicle")
  281. .ReturnsFromEntitySet<Vehicle>("vehicles");
  282. builder
  283. .Action("PostMotorcycle_When_Expecting_Car")
  284. .ReturnsFromEntitySet<Car>("cars");
  285. builder
  286. .Action("PatchMotorcycle_When_Expecting_Car")
  287. .ReturnsFromEntitySet<Car>("cars");
  288. return builder.GetEdmModel();
  289. }
  290. private static string GetODataPath(string url)
  291. {
  292. string serverBaseUri = "http://localhost/";
  293. Assert.True(url.StartsWith(serverBaseUri)); // Guard
  294. return url.Substring(serverBaseUri.Length);
  295. }
  296. }
  297. public class InheritanceController : ODataController
  298. {
  299. private Motorcycle motorcycle = new Motorcycle { Model = 2009, Name = "sample motorcycle", CanDoAWheelie = true };
  300. private Car car = new Car { Model = 2009, Name = "sample car", SeatingCapacity = 5 };
  301. private SportBike sportBike = new SportBike { Model = 2009, Name = "sample sportsbike", CanDoAWheelie = true, SportBikeProperty_NotVisible = 100 };
  302. public Vehicle GetMotorcycleAsVehicle()
  303. {
  304. return motorcycle;
  305. }
  306. public Vehicle GetCarAsVehicle()
  307. {
  308. return car;
  309. }
  310. public Vehicle GetSportBikeAsVehicle()
  311. {
  312. return sportBike;
  313. }
  314. public IEnumerable<Vehicle> GetVehicles()
  315. {
  316. return new Vehicle[] { motorcycle, car, sportBike };
  317. }
  318. public Motorcycle PostMotorcycle_When_Expecting_Motorcycle(Motorcycle motorcycle)
  319. {
  320. Assert.IsType<Motorcycle>(motorcycle);
  321. return motorcycle;
  322. }
  323. public Motorcycle PatchMotorcycle_When_Expecting_Motorcycle(Delta<Motorcycle> patch)
  324. {
  325. patch.Patch(motorcycle);
  326. return motorcycle;
  327. }
  328. public Motorcycle PutMotorcycle_When_Expecting_Motorcycle(Delta<Motorcycle> patch)
  329. {
  330. patch.Put(motorcycle);
  331. return motorcycle;
  332. }
  333. public Vehicle PostMotorcycle_When_Expecting_Vehicle(Vehicle motorcycle)
  334. {
  335. Assert.IsType<Motorcycle>(motorcycle);
  336. return motorcycle;
  337. }
  338. public Vehicle PatchMotorcycle_When_Expecting_Vehicle(Delta<Vehicle> patch)
  339. {
  340. Assert.IsType<Motorcycle>(patch.GetEntity());
  341. patch.Patch(motorcycle);
  342. return motorcycle;
  343. }
  344. }
  345. }