Example #1
0
        public virtual void QueryableUsesConfiguredAssembliesResolver_For_MappingDerivedTypes()
        {
            // Arrange
            QueryableAttribute        attribute             = new QueryableAttribute();
            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 InvalidActionReturnType_Throws(string actionName)
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();
            HttpRequestMessage request   = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Customer?$skip=1");
            HttpConfiguration  config    = new HttpConfiguration();

            request.Properties[HttpPropertyKeys.HttpConfigurationKey] = 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(actionName));
            HttpActionContext         actionContext        = new HttpActionContext(controllerContext, actionDescriptor);
            HttpActionExecutedContext context = new HttpActionExecutedContext(actionContext, null);

            context.Response = new HttpResponseMessage(HttpStatusCode.OK);
            Type   returnType = actionDescriptor.ReturnType;
            object instance   = returnType.IsArray ? Array.CreateInstance(returnType.GetElementType(), 5) : Activator.CreateInstance(returnType);

            context.Response.Content = new ObjectContent(returnType, instance, new JsonMediaTypeFormatter());

            // Act & Assert
            Assert.Throws <InvalidOperationException>(
                () => attribute.OnActionExecuted(context),
                String.Format(
                    "The action '{0}' on controller '{1}' with return type '{2}' cannot support querying. Ensure the type of the returned content is IEnumerable, IQueryable, or a generic form of either interface.",
                    actionName,
                    controllerDescriptor.ControllerName,
                    actionDescriptor.ReturnType.FullName));
        }
Example #3
0
        public static void Register(HttpConfiguration config)
        {
            config.Routes.MapODataRoute("Nephos", "sdata", GetImplicitEDM());

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
                );

            // Uncomment the following line of code to enable query support for actions with an IQueryable or IQueryable<T> return type.
            // To avoid processing unexpected or malicious queries, use the validation settings on QueryableAttribute to validate incoming queries.
            // For more information, visit http://go.microsoft.com/fwlink/?LinkId=279712.
            var queryAttribute = new QueryableAttribute()
            {
                AllowedQueryOptions = AllowedQueryOptions.All, // or just some: AllowedQueryOptions.Top | AllowedQueryOptions.Skip,
                MaxTop   = 100,
                PageSize = 100,
            };

            //config.EnableQuerySupport(queryAttribute);
            // no argument also allowed and then specify queryable attribute on controller
            config.EnableQuerySupport();

            // To disable tracing in your application, please comment out or remove the following line of code
            // For more information, refer to: http://www.asp.net/web-api
            config.EnableSystemDiagnosticsTracing();

            SDataMessageHandler sdataHandler = new SDataMessageHandler();

            // optionally add mapper that's a work around for web api odata not supporting property name aiasing
            sdataHandler.AddContentMap(new DefaultMetadataMap());
            sdataHandler.SetErrorResponseBuilder(new DefaultErrorResponseBuilder());
            GlobalConfiguration.Configuration.MessageHandlers.Add(sdataHandler);
        }
Example #4
0
        public void Primitives_Cannot_Be_Used_By_Filter_And_OrderBy(string filter)
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();
            HttpRequestMessage request   = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Primitive/?" + filter);
            HttpConfiguration  config    = new HttpConfiguration();

            request.Properties[HttpPropertyKeys.HttpConfigurationKey] = 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);
            context.Response.Content = new ObjectContent(typeof(object), new List <int>(), new JsonMediaTypeFormatter());

            // Act and Assert
            attribute.OnActionExecuted(context);
            HttpResponseMessage response = context.Response;

            Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
            Assert.IsAssignableFrom(typeof(ObjectContent), response.Content);
            Assert.IsType(typeof(HttpError), ((ObjectContent)response.Content).Value);
            Assert.Equal("Only $skip and $top OData query options are supported for this type.",
                         ((HttpError)((ObjectContent)response.Content).Value).Message);
        }
Example #5
0
        public void Primitives_Can_Be_Used_For_Top_And_Skip(string filter)
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();
            HttpRequestMessage request   = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Primitive/?" + filter);
            HttpConfiguration  config    = new HttpConfiguration();

            request.Properties[HttpPropertyKeys.HttpConfigurationKey] = 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(object), 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);
        }
Example #6
0
        public void ApplyQuery_SingleEntity_ThrowsArgumentNull_QueryOptions()
        {
            QueryableAttribute attribute = new QueryableAttribute();

            Assert.ThrowsArgumentNull(
                () => attribute.ApplyQuery(entity: 42, queryOptions: null),
                "queryOptions");
        }
Example #7
0
        public void ApplyQuery_Throws_WithNullQueryOptions()
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();

            // Act & Assert
            Assert.ThrowsArgumentNull(() => attribute.ApplyQuery(CustomerList.AsQueryable(), null), "queryOptions");
        }
Example #8
0
        public void ValidateQuery_Throws_With_Null_Request()
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();

            // Act & Assert
            Assert.ThrowsArgumentNull(() => attribute.ValidateQuery(null), "request");
        }
        public void ValidateQuery_Throws_WithNullQueryOptions()
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();

            // Act & Assert
            Assert.ThrowsArgumentNull(() => attribute.ValidateQuery(new HttpRequestMessage(), null), "queryOptions");
        }
Example #10
0
        public void ValidateQuery_Accepts_All_Supported_QueryNames(string queryName)
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();
            HttpRequestMessage request   = new HttpRequestMessage(HttpMethod.Get, "http://localhost/?" + queryName);

            // Act & Assert
            attribute.ValidateQuery(request);
        }
Example #11
0
        public void Ctor_Initializes_Properties()
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();

            // Act & Assert
            Assert.Equal(HandleNullPropagationOption.Default, attribute.HandleNullPropagation);
            Assert.True(attribute.EnsureStableOrdering);
        }
Example #12
0
        public void OnActionExecuted_SingleResult_Returns400_IfQueryContainsNonSelectExpand()
        {
            HttpActionExecutedContext actionExecutedContext = GetActionExecutedContext("http://localhost/?$top=10", new Customer());
            QueryableAttribute        attribute             = new QueryableAttribute();

            attribute.OnActionExecuted(actionExecutedContext);

            Assert.Equal(HttpStatusCode.BadRequest, actionExecutedContext.Response.StatusCode);
        }
        public void Ctor_Initializes_Properties()
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();

            // Act & Assert
            Assert.Equal(HandleNullPropagationOption.Default, attribute.HandleNullPropagation);
            Assert.True(attribute.EnsureStableOrdering);
        }
Example #14
0
        public void SingleOrDefault_IQueryableOfT_ZeroElementsInSequence_ReturnsNull()
        {
            IQueryable <Customer> queryable        = Enumerable.Empty <Customer>().AsQueryable();
            HttpActionDescriptor  actionDescriptor = new Mock <HttpActionDescriptor>().Object;

            var result = QueryableAttribute.SingleOrDefault(queryable, actionDescriptor);

            Assert.Null(result);
        }
Example #15
0
        public void ApplyQuery_SingleEntity_ThrowsArgumentNull_Entity()
        {
            QueryableAttribute attribute = new QueryableAttribute();
            ODataQueryOptions  options   = new ODataQueryOptions(new ODataQueryContext(EdmCoreModel.Instance, typeof(int)), new HttpRequestMessage());

            Assert.ThrowsArgumentNull(
                () => attribute.ApplyQuery(entity: null, queryOptions: options),
                "entity");
        }
Example #16
0
        public void SingleOrDefault_IQueryableOfT_OneElementInSequence_ReturnsElement()
        {
            Customer customer = new Customer();
            IQueryable <Customer> queryable = new[] { customer }.AsQueryable();
            HttpActionDescriptor  actionDescriptor = new Mock <HttpActionDescriptor>().Object;

            var result = QueryableAttribute.SingleOrDefault(queryable, actionDescriptor);

            Assert.Same(customer, result);
        }
        public void ValidateQuery_Throws_With_Null_Request()
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();
            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), "Customers"), new HttpRequestMessage());

            // Act & Assert
            Assert.ThrowsArgumentNull(() => attribute.ValidateQuery(null, options), "request");
        }
Example #18
0
        public void OrderByAllowedPropertiesWithSpaces(string allowedProperties)
        {
            QueryableAttribute attribute = new QueryableAttribute();

            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));
        }
Example #19
0
        public void OrderByDisllowedPropertiesWithSpaces(string allowedProperties)
        {
            QueryableAttribute attribute = new QueryableAttribute();

            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 QueryableAttribute or QueryValidationSettings.");
        }
Example #20
0
        public void ApplyQuery_Accepts_All_Supported_QueryNames(string query)
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();
            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));
        }
Example #21
0
        public void OnActionExecuted_SingleResult_WithMoreThanASingleQueryResult_ThrowsInvalidOperationException()
        {
            // Arrange
            var          customers = CustomerList.AsQueryable();
            SingleResult result    = SingleResult.Create(customers);
            HttpActionExecutedContext actionExecutedContext = GetActionExecutedContext("http://localhost/", result);
            QueryableAttribute        attribute             = new QueryableAttribute();

            // Act and Assert
            Assert.Throws <InvalidOperationException>(() => attribute.OnActionExecuted(actionExecutedContext));
        }
        public void ValidateQuery_Accepts_All_Supported_QueryNames(string queryName)
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();
            HttpRequestMessage request   = new HttpRequestMessage(HttpMethod.Get, "http://localhost/?" + queryName + "=x");
            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), "Customers"), request);

            // Act & Assert
            attribute.ValidateQuery(request, options);
        }
Example #23
0
        public void GetFilters_ReturnsQueryableFilter_ForQueryableActions(string actionName)
        {
            HttpConfiguration        config = new HttpConfiguration();
            HttpControllerDescriptor controllerDescriptor = new HttpControllerDescriptor(config, "FilterProviderTest", typeof(FilterProviderTestController));
            HttpActionDescriptor     actionDescriptor     = new ReflectedHttpActionDescriptor(controllerDescriptor, typeof(FilterProviderTestController).GetMethod(actionName));

            FilterInfo[] filters = new QueryFilterProvider(new QueryableAttribute()).GetFilters(config, actionDescriptor).ToArray();

            Assert.Equal(1, filters.Length);
            Assert.Equal(FilterScope.Global, filters[0].Scope);
            QueryableAttribute filter = Assert.IsType <QueryableAttribute>(filters[0].Instance);
        }
Example #24
0
        public void QueryableOnActionUnknownOperatorStartingDollarSignThrows()
        {
            QueryableAttribute        attribute             = new QueryableAttribute();
            HttpActionExecutedContext actionExecutedContext = GetActionExecutedContext(
                "http://localhost:8080/QueryCompositionCustomer?$orderby=Name desc&$unknown=12",
                QueryCompositionCustomerController.CustomerList.AsQueryable());

            var exception = Assert.Throws <HttpResponseException>(() => attribute.OnActionExecuted(actionExecutedContext));

            // QueryableAttribute will validate and throws
            Assert.Equal(HttpStatusCode.BadRequest, exception.Response.StatusCode);
        }
Example #25
0
        public void ApplyQuery_CallsApplyOnODataQueryOptions()
        {
            object                   entity       = new object();
            QueryableAttribute       attribute    = new QueryableAttribute();
            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());
        }
Example #26
0
        public void OnActionExecuted_SingleResult_ReturnsSingleItemEvenIfThereIsNoSelectExpand()
        {
            Customer     customer     = new Customer();
            SingleResult singleResult = new SingleResult <Customer>(new Customer[] { customer }.AsQueryable());
            HttpActionExecutedContext actionExecutedContext = GetActionExecutedContext("http://localhost/", singleResult);
            QueryableAttribute        attribute             = new QueryableAttribute();

            attribute.OnActionExecuted(actionExecutedContext);

            Assert.Equal(HttpStatusCode.OK, actionExecutedContext.Response.StatusCode);
            Assert.Equal(customer, (actionExecutedContext.Response.Content as ObjectContent).Value);
        }
Example #27
0
        public void ValidateQuery_Sends_BadRequest_For_Unrecognized_QueryNames()
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();
            HttpRequestMessage request   = new HttpRequestMessage(HttpMethod.Get, "http://localhost/?$xxx");

            // Act & Assert
            HttpResponseException responseException = Assert.Throws <HttpResponseException>(
                () => attribute.ValidateQuery(request));

            Assert.Equal(HttpStatusCode.BadRequest, responseException.Response.StatusCode);
        }
Example #28
0
        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>(
                () => QueryableAttribute.ValidateSelectExpandOnly(queryOptions),
                "The requested resource is not a collection. Query options $filter, $orderby, $inlinecount, $skip, and $top can be applied only on collections.");
        }
Example #29
0
        public void ValidateQuery_Can_Override_Base()
        {
            // Arrange
            Mock <QueryableAttribute> mockAttribute = new Mock <QueryableAttribute>();

            mockAttribute.Setup(m => m.ValidateQuery(It.IsAny <HttpRequestMessage>())).Callback(() => { }).Verifiable();

            QueryableAttribute attribute = new QueryableAttribute();
            HttpRequestMessage request   = new HttpRequestMessage(HttpMethod.Get, "http://localhost/?$xxx");

            // Act & Assert
            mockAttribute.Object.ValidateQuery(null);
            mockAttribute.Verify();
        }
        public void ValidateQuery_Sends_BadRequest_For_Unrecognized_QueryNames()
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();
            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), "Customers"), request);

            // Act & Assert
            HttpResponseException responseException = Assert.Throws <HttpResponseException>(
                () => attribute.ValidateQuery(request, options));

            Assert.Equal(HttpStatusCode.BadRequest, responseException.Response.StatusCode);
        }
Example #31
0
        /// <summary>
        /// Initializes a new instance of the <see cref="TableFilterProvider"/> using the provided <see cref="QueryableAttribute"/>
        /// implementation for executing the query.
        /// </summary>
        public TableFilterProvider(IActionFilter queryFilter)
        {
            if (queryFilter == null)
            {
                throw new ArgumentNullException("queryFilter");
            }

            this.queryFilter = new QueryableAttribute()
            {
                PageSize = TableUtils.PageSize
            };
            this.queryFilterProvider = new QueryFilterProvider(queryFilter);
            this.tableFilter         = new FilterInfo(new TableQueryFilter(), FilterScope.Global);
        }
        public void UnknownQueryNotStartingWithDollarSignWorks()
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Customer/?select");
            HttpConfiguration config = new HttpConfiguration();
            request.Properties[HttpPropertyKeys.HttpConfigurationKey] = 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("Get"));
            HttpActionContext actionContext = new HttpActionContext(controllerContext, actionDescriptor);
            HttpActionExecutedContext context = new HttpActionExecutedContext(actionContext, null);
            context.Response = new HttpResponseMessage(HttpStatusCode.OK);
            context.Response.Content = new ObjectContent(typeof(object), new List<Customer>(), new JsonMediaTypeFormatter());

            // Act and Assert
            attribute.OnActionExecuted(context);

            Assert.Equal(HttpStatusCode.OK, context.Response.StatusCode);
        }
        public void DifferentReturnTypeWorks(string methodName, object responseObject, bool isNoOp)
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Customer/?$orderby=Name");
            HttpConfiguration config = new HttpConfiguration();
            request.Properties[HttpPropertyKeys.HttpConfigurationKey] = 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(methodName));
            HttpActionContext actionContext = new HttpActionContext(controllerContext, actionDescriptor);
            HttpActionExecutedContext context = new HttpActionExecutedContext(actionContext, null);
            context.Response = new HttpResponseMessage(HttpStatusCode.OK);
            context.Response.Content = new ObjectContent(typeof(object), responseObject, new JsonMediaTypeFormatter());

            // Act and Assert
            attribute.OnActionExecuted(context);

            Assert.Equal(HttpStatusCode.OK, context.Response.StatusCode);
            Assert.True(context.Response.Content is ObjectContent);
            Assert.Equal(isNoOp, ((ObjectContent)context.Response.Content).Value == responseObject);
        }
        public void OnActionExecuted_Throws_Null_Configuration()
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Customer/?$orderby=Name");
            HttpConfiguration config = new HttpConfiguration();
            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("Get"));
            HttpActionContext actionContext = new HttpActionContext(controllerContext, actionDescriptor);
            HttpActionExecutedContext context = new HttpActionExecutedContext(actionContext, null);

            Assert.ThrowsArgument(
                () => new QueryableAttribute().OnActionExecuted(context), 
                "actionExecutedContext",
                String.Format("Request message does not contain an HttpConfiguration object.{0}Parameter name: actionExecutedContext", Environment.NewLine));
        }
        public void ValidateQuery_Sends_BadRequest_For_Unrecognized_QueryNames()
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();
            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), "Customers"), request);

            // Act & Assert
            HttpResponseException responseException = Assert.Throws<HttpResponseException>(
                                                                () => attribute.ValidateQuery(request, options));

            Assert.Equal(HttpStatusCode.BadRequest, responseException.Response.StatusCode);
        }
        public void ValidateQuery_Accepts_All_Supported_QueryNames(string queryName)
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/?" + queryName + "=x");
            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), "Customers"), request);

            // Act & Assert
            attribute.ValidateQuery(request, options);
        }
        public void OrderByAllowedPropertiesWithSpaces(string allowedProperties)
        {
            QueryableAttribute attribute = new QueryableAttribute();
            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 ValidateQuery_Can_Override_Base()
        {
            // Arrange
            Mock<QueryableAttribute> mockAttribute = new Mock<QueryableAttribute>();
            mockAttribute.Setup(m => m.ValidateQuery(It.IsAny<HttpRequestMessage>())).Callback(() => { }).Verifiable();

            QueryableAttribute attribute = new QueryableAttribute();
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/?$xxx");

            // Act & Assert
            mockAttribute.Object.ValidateQuery(null);
            mockAttribute.Verify();
        }
        public void ValidateQuery_Accepts_All_Supported_QueryNames(string queryName)
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/?" + queryName);

            // Act & Assert
            attribute.ValidateQuery(request);
        }
        public void Primitives_Cannot_Be_Used_By_Filter_And_OrderBy(string filter)
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Primitive/?" + filter);
            HttpConfiguration config = new HttpConfiguration();
            request.Properties[HttpPropertyKeys.HttpConfigurationKey] = 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);
            context.Response.Content = new ObjectContent(typeof(object), new List<int>(), new JsonMediaTypeFormatter());

            // Act and Assert
            attribute.OnActionExecuted(context);
            HttpResponseMessage response = context.Response;

            Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
            Assert.IsAssignableFrom(typeof(ObjectContent), response.Content);
            Assert.IsType(typeof(HttpError), ((ObjectContent)response.Content).Value);
            Assert.Equal("Only $skip and $top OData query options are supported for this type.",
                         ((HttpError)((ObjectContent)response.Content).Value).Message);
        }
        public void NonGenericEnumerableReturnTypeThrows()
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Customer/?$skip=1");
            HttpConfiguration config = new HttpConfiguration();
            config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
            request.Properties[HttpPropertyKeys.HttpConfigurationKey] = 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 & Assert
            Assert.Throws<InvalidOperationException>(
                () => attribute.OnActionExecuted(context),
                "Cannot create an EDM model as the action 'QueryableAttribute' on controller 'GetNonGenericEnumerable' has a return type 'CustomerHighLevel' that does not implement IEnumerable<T>.");
        }
        public void ApplyQuery_Throws_WithNullQueryOptions()
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();

            // Act & Assert
            Assert.ThrowsArgumentNull(() => attribute.ApplyQuery(CustomerList.AsQueryable(), null), "queryOptions");
        }
        public void CreateQueryContext_ReturnsQueryContext_ForMatchingModelOnRequest()
        {
            var builder = new ODataConventionModelBuilder();
            builder.EntitySet<QueryCompositionCustomer>("customers");
            var model = builder.GetEdmModel();
            var entityClrType = typeof(QueryCompositionCustomer);
            var config = new HttpConfiguration();
            var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/");
            request.SetEdmModel(model);
            var descriptor = new ReflectedHttpActionDescriptor();
            descriptor.Configuration = config;

            var queryModel = new QueryableAttribute().GetModel(entityClrType, request, descriptor);

            Assert.NotNull(queryModel);
            Assert.Same(model, queryModel);
            Assert.False(descriptor.Properties.ContainsKey("MS_EdmModelSystem.Web.Http.OData.Query.QueryCompositionCustomer"));
        }
 public void ApplyQuery_Accepts_All_Supported_QueryNames(string query)
 {
     // Arrange
     QueryableAttribute attribute = new QueryableAttribute();
     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 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 QueryableAttribute().GetModel(entityClrType, request, descriptor);

            Assert.NotNull(queryModel);
            Assert.Same(descriptor.Properties["MS_EdmModelSystem.Web.Http.OData.Query.QueryCompositionCustomer"], queryModel);
        }
        public void NonGenericEnumerableReturnTypeThrows()
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Customer/?$skip=1");
            HttpConfiguration config = new HttpConfiguration();
            config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
            request.Properties[HttpPropertyKeys.HttpConfigurationKey] = 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(object), new NonGenericEnumerable(), new JsonMediaTypeFormatter());

            // Act & Assert
            Assert.Throws<InvalidOperationException>(
                () => attribute.OnActionExecuted(context),
                "The 'QueryableAttribute' type cannot be used with action 'GetNonGenericEnumerable' on controller 'CustomerHighLevel' because the return type 'System.Web.Http.OData.TestCommon.Models.NonGenericEnumerable' does not specify the type of the collection.");
        }
        public void NonObjectContentResponse_ThrowsInvalidOperationException()
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Customer?$skip=1");
            HttpConfiguration config = new HttpConfiguration();
            request.Properties[HttpPropertyKeys.HttpConfigurationKey] = 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);
            context.Response = new HttpResponseMessage(HttpStatusCode.OK);
            context.Response.Content = new StreamContent(new MemoryStream());

            // Act & Assert
            Assert.Throws<InvalidOperationException>(
                () => attribute.OnActionExecuted(context),
                "Queries can not be applied to a response content of type 'System.Net.Http.StreamContent'. The response content must be an ObjectContent.");
        }
        public void Primitives_Can_Be_Used_For_Top_And_Skip(string filter)
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Primitive/?" + filter);
            HttpConfiguration config = new HttpConfiguration();
            request.Properties[HttpPropertyKeys.HttpConfigurationKey] = 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(object), 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 InvalidActionReturnType_Throws(string actionName)
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Customer?$skip=1");
            HttpConfiguration config = new HttpConfiguration();
            request.Properties[HttpPropertyKeys.HttpConfigurationKey] = 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(actionName));
            HttpActionContext actionContext = new HttpActionContext(controllerContext, actionDescriptor);
            HttpActionExecutedContext context = new HttpActionExecutedContext(actionContext, null);
            context.Response = new HttpResponseMessage(HttpStatusCode.OK);
            Type returnType = actionDescriptor.ReturnType;
            object instance = returnType.IsArray ? Array.CreateInstance(returnType.GetElementType(), 5) : Activator.CreateInstance(returnType);
            context.Response.Content = new ObjectContent(returnType, instance, new JsonMediaTypeFormatter());

            // Act & Assert
            Assert.Throws<InvalidOperationException>(
                () => attribute.OnActionExecuted(context),
                String.Format(
                    "The action '{0}' on controller '{1}' with return type '{2}' cannot support querying. Ensure the type of the returned content is IEnumerable, IQueryable, or a generic form of either interface.",
                    actionName,
                    controllerDescriptor.ControllerName,
                    actionDescriptor.ReturnType.FullName));
        }
        public void ValidateQuery_Throws_With_Null_Request()
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();

            // Act & Assert
            Assert.ThrowsArgumentNull(() => attribute.ValidateQuery(null), "request");
        }
        public void ValidateQuery_Throws_With_Null_Request()
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();
            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), "Customers"), new HttpRequestMessage());

            // Act & Assert
            Assert.ThrowsArgumentNull(() => attribute.ValidateQuery(null, options), "request");
        }
        public void ValidateQuery_Sends_BadRequest_For_Unrecognized_QueryNames()
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/?$xxx");

            // Act & Assert
            HttpResponseException responseException = Assert.Throws<HttpResponseException>(
                                                                () => attribute.ValidateQuery(request));

            Assert.Equal(HttpStatusCode.BadRequest, responseException.Response.StatusCode);
        }
        public void ValidateQuery_Throws_WithNullQueryOptions()
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();

            // Act & Assert
            Assert.ThrowsArgumentNull(() => attribute.ValidateQuery(new HttpRequestMessage(), null), "queryOptions");
        }
        public void UnknownQueryStartingWithDollarSignThrows()
        {
            // Arrange
            QueryableAttribute attribute = new QueryableAttribute();
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Customer/?$custom");
            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("Get"));
            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<Customer>), new List<Customer>(), new JsonMediaTypeFormatter());

            // Act and Assert
            HttpResponseException errorResponse = Assert.Throws<HttpResponseException>(() =>
                attribute.OnActionExecuted(context));

            Assert.Equal(HttpStatusCode.BadRequest, errorResponse.Response.StatusCode);
        }
        public void OrderByDisllowedPropertiesWithSpaces(string allowedProperties)
        {
            QueryableAttribute attribute = new QueryableAttribute();
            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 QueryableAttribute or QueryValidationSettings.");
        }