public void NonGenericEnumerableReturnType_ReturnsBadRequest() { // Arrange EnableQueryAttribute attribute = new EnableQueryAttribute(); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Customer/?$skip=1"); HttpConfiguration config = new HttpConfiguration(); config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always; request.SetConfiguration(config); HttpControllerContext controllerContext = new HttpControllerContext(config, new HttpRouteData(new HttpRoute()), request); HttpControllerDescriptor controllerDescriptor = new HttpControllerDescriptor(new HttpConfiguration(), "CustomerHighLevel", typeof(CustomerHighLevelController)); HttpActionDescriptor actionDescriptor = new ReflectedHttpActionDescriptor(controllerDescriptor, typeof(CustomerHighLevelController).GetMethod("GetNonGenericEnumerable")); HttpActionContext actionContext = new HttpActionContext(controllerContext, actionDescriptor); HttpActionExecutedContext context = new HttpActionExecutedContext(actionContext, null); context.Response = new HttpResponseMessage(HttpStatusCode.OK); context.Response.Content = new ObjectContent(typeof(IEnumerable), new NonGenericEnumerable(), new JsonMediaTypeFormatter()); // Act attribute.OnActionExecuted(context); string responseString = context.Response.Content.ReadAsStringAsync().Result; // Assert Assert.Equal(HttpStatusCode.BadRequest, context.Response.StatusCode); Assert.Contains("The query specified in the URI is not valid. Cannot create an EDM model as the action 'EnableQueryAttribute' " + "on controller 'GetNonGenericEnumerable' has a return type 'CustomerHighLevel' that does not implement IEnumerable<T>.", responseString); }
public void SingleOrDefault_DisposeCalled_OneElementInSequence() { // Arrange var enumerator = new Mock <IEnumerator>(MockBehavior.Strict); enumerator.SetupSequence(mock => mock.MoveNext()).Returns(true).Returns(false); enumerator.SetupGet(mock => mock.Current).Returns(new Customer()); var disposable = enumerator.As <IDisposable>(); disposable.Setup(mock => mock.Dispose()).Verifiable(); var queryable = new Mock <IQueryable>(MockBehavior.Strict); queryable.Setup(mock => mock.GetEnumerator()).Returns(enumerator.Object); var actionDescriptor = new ReflectedHttpActionDescriptor { Configuration = new HttpConfiguration(), MethodInfo = GetType().GetMethod("SomeAction", BindingFlags.Instance | BindingFlags.NonPublic), ControllerDescriptor = new HttpControllerDescriptor { ControllerName = "SomeName" } }; // Act EnableQueryAttribute.SingleOrDefault(queryable.Object, actionDescriptor); // Assert disposable.Verify(); }
public void Primitives_Can_Be_Used_For_Top_And_Skip(string filter) { // Arrange EnableQueryAttribute attribute = new EnableQueryAttribute(); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Primitive/?" + filter); HttpConfiguration config = new HttpConfiguration(); request.SetConfiguration(config); HttpControllerContext controllerContext = new HttpControllerContext(config, new HttpRouteData(new HttpRoute()), request); HttpControllerDescriptor controllerDescriptor = new HttpControllerDescriptor(new HttpConfiguration(), "Primitive", typeof(PrimitiveController)); HttpActionDescriptor actionDescriptor = new ReflectedHttpActionDescriptor(controllerDescriptor, typeof(PrimitiveController).GetMethod("GetIEnumerableOfInt")); HttpActionContext actionContext = new HttpActionContext(controllerContext, actionDescriptor); HttpActionExecutedContext context = new HttpActionExecutedContext(actionContext, null); context.Response = new HttpResponseMessage(HttpStatusCode.OK); HttpContent expectedResponse = new ObjectContent(typeof(IEnumerable <int>), new List <int>(), new JsonMediaTypeFormatter()); context.Response.Content = expectedResponse; // Act and Assert attribute.OnActionExecuted(context); HttpResponseMessage response = context.Response; Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(expectedResponse, response.Content); }
public void NullContentResponse_DoesNotThrow() { // Arrange EnableQueryAttribute attribute = new EnableQueryAttribute(); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Customer?$skip=1"); HttpConfiguration config = new HttpConfiguration(); request.SetConfiguration(config); HttpControllerContext controllerContext = new HttpControllerContext( config, new HttpRouteData(new HttpRoute()), request); HttpControllerDescriptor controllerDescriptor = new HttpControllerDescriptor( new HttpConfiguration(), "CustomerHighLevel", typeof(CustomerHighLevelController)); HttpActionDescriptor actionDescriptor = new ReflectedHttpActionDescriptor( controllerDescriptor, typeof(CustomerHighLevelController).GetMethod("GetIEnumerableOfCustomer")); HttpActionContext actionContext = new HttpActionContext(controllerContext, actionDescriptor); HttpActionExecutedContext context = new HttpActionExecutedContext(actionContext, null) { Response = new HttpResponseMessage(HttpStatusCode.OK) { Content = null } }; // Act & Assert Assert.DoesNotThrow(() => attribute.OnActionExecuted(context)); }
public ODataBinding(ODataContext context, EnableQueryAttribute attribute, Type type) { _context = context ?? throw new ArgumentNullException(nameof(context)); _attribute = attribute ?? throw new ArgumentNullException(nameof(attribute)); _type = type ?? throw new ArgumentNullException(nameof(type)); _optionsBuilder = BuildODataQueryOptionsFactory(_type); }
public virtual void QueryableUsesConfiguredAssembliesResolver_For_MappingDerivedTypes() { // Arrange EnableQueryAttribute attribute = new EnableQueryAttribute(); HttpActionExecutedContext actionExecutedContext = GetActionExecutedContext( "http://localhost:8080/QueryCompositionCustomer/?$filter=Id eq 2", QueryCompositionCustomerController.CustomerList.AsQueryable()); ODataModelBuilder modelBuilder = new ODataConventionModelBuilder(); modelBuilder.EntitySet <QueryCompositionCustomer>(typeof(QueryCompositionCustomer).Name); IEdmModel model = modelBuilder.GetEdmModel(); model.SetAnnotationValue <ClrTypeAnnotation>(model.FindType("System.Web.Http.OData.Query.QueryCompositionCustomer"), null); bool called = false; Mock <IAssembliesResolver> assembliesResolver = new Mock <IAssembliesResolver>(); assembliesResolver .Setup(r => r.GetAssemblies()) .Returns(new DefaultAssembliesResolver().GetAssemblies()) .Callback(() => { called = true; }) .Verifiable(); actionExecutedContext.Request.GetConfiguration().Services.Replace(typeof(IAssembliesResolver), assembliesResolver.Object); // Act attribute.OnActionExecuted(actionExecutedContext); // Assert Assert.True(called); }
public void ApplyQuery_Throws_WithNullQueryOptions() { // Arrange EnableQueryAttribute attribute = new EnableQueryAttribute(); // Act & Assert Assert.ThrowsArgumentNull(() => attribute.ApplyQuery(CustomerList.AsQueryable(), null), "queryOptions"); }
public void ValidateQuery_Throws_WithNullQueryOptions() { // Arrange EnableQueryAttribute attribute = new EnableQueryAttribute(); // Act & Assert Assert.ThrowsArgumentNull(() => attribute.ValidateQuery(new HttpRequestMessage(), null), "queryOptions"); }
public void ApplyQuery_SingleEntity_ThrowsArgumentNull_QueryOptions() { EnableQueryAttribute attribute = new EnableQueryAttribute(); Assert.ThrowsArgumentNull( () => attribute.ApplyQuery(entity: 42, queryOptions: null), "queryOptions"); }
public void RunQueryableOnAllPossibleTypes(Type type, string queryString) { int seed = RandomSeedGenerator.GetRandomSeed(); Random r = new Random(seed); Type generic = typeof(IEnumerable <>); var collectionType = generic.MakeGenericType(type); Type listType = typeof(List <>).MakeGenericType(type); var array = Activator.CreateInstance(listType); EnableQueryAttribute q = new EnableQueryAttribute(); var configuration = new HttpConfiguration(); configuration.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always; configuration.Count().Filter().OrderBy().Expand().MaxTop(null).Select(); configuration.Routes.MapHttpRoute("ApiDefault", "api/{controller}/{id}", new { id = RouteParameter.Optional }); configuration.EnableDependencyInjection(); var request = new HttpRequestMessage(HttpMethod.Get, "http://test/api/Objects?" + queryString); request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, configuration); var controllerContext = new HttpControllerContext( configuration, configuration.Routes.GetRouteData(request), request); var actionContext = new HttpActionContext(controllerContext, new ReflectedHttpActionDescriptor() { Configuration = configuration }); var context = new HttpActionExecutedContext(actionContext, null); context.Response = new HttpResponseMessage(System.Net.HttpStatusCode.OK); context.Response.Content = new ObjectContent(collectionType, array, new JsonMediaTypeFormatter()); try { q.OnActionExecuted(context); Console.WriteLine(context.Response.Content.ReadAsStringAsync().Result); Assert.Equal(HttpStatusCode.OK, context.Response.StatusCode); } catch (ArgumentException ae) { // For example: // The type 'System.DateTime' of property 'NotAfter' in the // 'System.Security.Cryptography.X509Certificates.X509Certificate2' type is not a supported type. // Change to use 'System.DateTimeOffset' or ignore this type by calling // Ignore<System.Security.Cryptography.X509Certificates.X509Certificate2>() // on 'System.Web.OData.Builder.ODataModelBuilder'. Assert.True(ae.Message.Contains("The type 'System.DateTime' of property") || ae.Message.Contains("System.Windows.Forms.AxHost") || ae.Message.Contains("Found more than one dynamic property container in type"), "The exception should contains \"The type 'System.DateTime' of property\", or " + "\"System.Windows.Forms.AxHost\" or" + "\"Found more than one dynamic property container in type\", but actually, it is:" + ae.Message); } }
public void Ctor_Initializes_Properties() { // Arrange EnableQueryAttribute attribute = new EnableQueryAttribute(); // Act & Assert Assert.Equal(HandleNullPropagationOption.Default, attribute.HandleNullPropagation); Assert.True(attribute.EnsureStableOrdering); }
public void SingleOrDefault_IQueryableOfT_ZeroElementsInSequence_ReturnsNull() { IQueryable <Customer> queryable = Enumerable.Empty <Customer>().AsQueryable(); HttpActionDescriptor actionDescriptor = new Mock <HttpActionDescriptor>().Object; var result = EnableQueryAttribute.SingleOrDefault(queryable, actionDescriptor); Assert.Null(result); }
public void ApplyQuery_SingleEntity_ThrowsArgumentNull_Entity() { EnableQueryAttribute attribute = new EnableQueryAttribute(); ODataQueryOptions options = new ODataQueryOptions(new ODataQueryContext(EdmCoreModel.Instance, typeof(int)), new HttpRequestMessage()); Assert.ThrowsArgumentNull( () => attribute.ApplyQuery(entity: null, queryOptions: options), "entity"); }
public void OnActionExecuted_SingleResult_Returns400_IfQueryContainsNonSelectExpand() { HttpActionExecutedContext actionExecutedContext = GetActionExecutedContext("http://localhost/?$top=10", new Customer()); EnableQueryAttribute attribute = new EnableQueryAttribute(); attribute.OnActionExecuted(actionExecutedContext); Assert.Equal(HttpStatusCode.BadRequest, actionExecutedContext.Response.StatusCode); }
public void OrderByAllowedPropertiesWithSpaces(string allowedProperties) { EnableQueryAttribute attribute = new EnableQueryAttribute(); attribute.AllowedOrderByProperties = allowedProperties; HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Customers/?$orderby=Id,Name"); ODataQueryOptions queryOptions = new ODataQueryOptions(ValidationTestHelper.CreateCustomerContext(), request); Assert.DoesNotThrow(() => attribute.ValidateQuery(request, queryOptions)); }
public void ApplyQuery_Throws_With_Null_Queryable() { // Arrange EnableQueryAttribute attribute = new EnableQueryAttribute(); var model = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetEdmModel(); var options = new ODataQueryOptions(new ODataQueryContext(model, typeof(System.Web.Http.OData.Builder.TestModels.Customer)), new HttpRequestMessage()); // Act & Assert Assert.ThrowsArgumentNull(() => attribute.ApplyQuery(null, options), "queryable"); }
public void SingleOrDefault_IQueryableOfT_OneElementInSequence_ReturnsElement() { Customer customer = new Customer(); IQueryable <Customer> queryable = new[] { customer }.AsQueryable(); HttpActionDescriptor actionDescriptor = new Mock <HttpActionDescriptor>().Object; var result = EnableQueryAttribute.SingleOrDefault(queryable, actionDescriptor); Assert.Same(customer, result); }
public void OrderByDisllowedPropertiesWithSpaces(string allowedProperties) { EnableQueryAttribute attribute = new EnableQueryAttribute(); attribute.AllowedOrderByProperties = allowedProperties; HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Customers/?$orderby=Id,Name"); ODataQueryOptions queryOptions = new ODataQueryOptions(ValidationTestHelper.CreateCustomerContext(), request); Assert.Throws <ODataException>(() => attribute.ValidateQuery(request, queryOptions), "Order by 'Name' is not allowed. To allow it, set the 'AllowedOrderByProperties' property on EnableQueryAttribute or QueryValidationSettings."); }
public void ApplyQuery_Accepts_All_Supported_QueryNames(string query) { // Arrange EnableQueryAttribute attribute = new EnableQueryAttribute(); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/?" + query); var model = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetEdmModel(); var options = new ODataQueryOptions(new ODataQueryContext(model, typeof(System.Web.Http.OData.Builder.TestModels.Customer)), request); // Act & Assert Assert.DoesNotThrow(() => attribute.ApplyQuery(new List <System.Web.Http.OData.Builder.TestModels.Customer>().AsQueryable(), options)); }
public void OnActionExecuted_SingleResult_WithMoreThanASingleQueryResult_ThrowsInvalidOperationException() { // Arrange var customers = CustomerList.AsQueryable(); SingleResult result = SingleResult.Create(customers); HttpActionExecutedContext actionExecutedContext = GetActionExecutedContext("http://localhost/", result); EnableQueryAttribute attribute = new EnableQueryAttribute(); // Act and Assert Assert.Throws <InvalidOperationException>(() => attribute.OnActionExecuted(actionExecutedContext)); }
public void ApplyQuery_CallsApplyOnODataQueryOptions() { object entity = new object(); EnableQueryAttribute attribute = new EnableQueryAttribute(); ODataQueryContext context = new ODataQueryContext(EdmCoreModel.Instance, typeof(int)); HttpRequestMessage request = new HttpRequestMessage(); Mock <ODataQueryOptions> queryOptions = new Mock <ODataQueryOptions>(context, request); attribute.ApplyQuery(entity, queryOptions.Object); queryOptions.Verify(q => q.ApplyTo(entity, It.IsAny <ODataQuerySettings>()), Times.Once()); }
public void QueryableOnActionUnknownOperatorStartingDollarSignThrows() { EnableQueryAttribute attribute = new EnableQueryAttribute(); HttpActionExecutedContext actionExecutedContext = GetActionExecutedContext( "http://localhost:8080/QueryCompositionCustomer?$orderby=Name desc&$unknown=12", QueryCompositionCustomerController.CustomerList.AsQueryable()); var exception = Assert.Throws <HttpResponseException>(() => attribute.OnActionExecuted(actionExecutedContext)); // EnableQueryAttribute will validate and throws Assert.Equal(HttpStatusCode.BadRequest, exception.Response.StatusCode); }
public void GetFilters_ReturnsQueryableFilter_ForQueryableActions(string actionName) { var config = RoutingConfigurationFactory.Create(); HttpControllerDescriptor controllerDescriptor = new HttpControllerDescriptor(config, "FilterProviderTest", typeof(FilterProviderTestController)); HttpActionDescriptor actionDescriptor = new ReflectedHttpActionDescriptor(controllerDescriptor, typeof(FilterProviderTestController).GetMethod(actionName)); FilterInfo[] filters = new QueryFilterProvider(new EnableQueryAttribute()).GetFilters(config, actionDescriptor).ToArray(); Assert.Single(filters); Assert.Equal(FilterScope.Global, filters[0].Scope); EnableQueryAttribute filter = Assert.IsType <EnableQueryAttribute>(filters[0].Instance); }
public void OnActionExecuted_SingleResult_ReturnsSingleItemEvenIfThereIsNoSelectExpand() { Customer customer = new Customer(); SingleResult singleResult = new SingleResult <Customer>(new Customer[] { customer }.AsQueryable()); HttpActionExecutedContext actionExecutedContext = GetActionExecutedContext("http://localhost/", singleResult); EnableQueryAttribute attribute = new EnableQueryAttribute(); attribute.OnActionExecuted(actionExecutedContext); Assert.Equal(HttpStatusCode.OK, actionExecutedContext.Response.StatusCode); Assert.Equal(customer, (actionExecutedContext.Response.Content as ObjectContent).Value); }
public void ValidateSelectExpandOnly_ThrowsODataException_IfODataQueryOptionsHasNonSelectExpand(string parameter) { CustomersModelWithInheritance model = new CustomersModelWithInheritance(); model.Model.SetAnnotationValue(model.Customer, new ClrTypeAnnotation(typeof(Customer))); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost?" + parameter); ODataQueryContext context = new ODataQueryContext(model.Model, typeof(Customer)); ODataQueryOptions queryOptions = new ODataQueryOptions(context, request); Assert.Throws <ODataException>( () => EnableQueryAttribute.ValidateSelectExpandOnly(queryOptions), "The requested resource is not a collection. Query options $filter, $orderby, $inlinecount, $skip, and $top can be applied only on collections."); }
public void QueryableOnActionUnknownOperatorIsAllowed() { EnableQueryAttribute attribute = new EnableQueryAttribute(); HttpActionExecutedContext actionExecutedContext = GetActionExecutedContext( "http://localhost:8080/?$orderby=$it desc&unknown=12", Enumerable.Range(0, 5).AsQueryable()); // unsupported operator - ignored attribute.OnActionExecuted(actionExecutedContext); List <int> result = actionExecutedContext.Response.Content.ReadAsAsync <List <int> >().Result; Assert.Equal(new[] { 4, 3, 2, 1, 0 }, result); }
public void OnActionExecuted_SingleResult_WithEmptyQueryResult_SetsNotFoundResponse() { // Arrange var customers = Enumerable.Empty <Customer>().AsQueryable(); SingleResult result = SingleResult.Create(customers); HttpActionExecutedContext actionExecutedContext = GetActionExecutedContext("http://localhost/", result); EnableQueryAttribute attribute = new EnableQueryAttribute(); // Act attribute.OnActionExecuted(actionExecutedContext); // Assert Assert.Equal(HttpStatusCode.NotFound, actionExecutedContext.Response.StatusCode); }
public void ValidateQuery_Sends_BadRequest_For_Unrecognized_QueryNames() { // Arrange EnableQueryAttribute attribute = new EnableQueryAttribute(); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/?$xxx"); var model = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetEdmModel(); var options = new ODataQueryOptions(new ODataQueryContext(model, typeof(System.Web.Http.OData.Builder.TestModels.Customer)), request); // Act & Assert HttpResponseException responseException = Assert.Throws <HttpResponseException>( () => attribute.ValidateQuery(request, options)); Assert.Equal(HttpStatusCode.BadRequest, responseException.Response.StatusCode); }
public void GetModel_ReturnsModel_ForNoModelOnRequest() { var entityClrType = typeof(QueryCompositionCustomer); var config = new HttpConfiguration(); var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/"); var descriptor = new ReflectedHttpActionDescriptor(); descriptor.Configuration = config; var queryModel = new EnableQueryAttribute().GetModel(entityClrType, request, descriptor); Assert.NotNull(queryModel); Assert.Same(descriptor.Properties["MS_EdmModelSystem.Web.Http.OData.Query.QueryCompositionCustomer"], queryModel); }
public void SingleOrDefault_IQueryableOfT_MoreThaneOneElementInSequence_Throws() { IQueryable <Customer> queryable = new[] { new Customer(), new Customer() }.AsQueryable(); ReflectedHttpActionDescriptor actionDescriptor = new ReflectedHttpActionDescriptor { Configuration = new HttpConfiguration(), MethodInfo = GetType().GetMethod("SomeAction", BindingFlags.Instance | BindingFlags.NonPublic), ControllerDescriptor = new HttpControllerDescriptor { ControllerName = "SomeName" } }; Assert.Throws <InvalidOperationException>( () => EnableQueryAttribute.SingleOrDefault(queryable, actionDescriptor), "The action 'SomeAction' on controller 'SomeName' returned a SingleResult containing more than one element. " + "SingleResult must have zero or one elements."); }