private Uri CreateEntryContextUri(string selectClause, string expandClause) { SelectExpandClause selectExpandClause = new ODataQueryOptionParser(edmModel, this.cityType, this.citySet, new Dictionary <string, string> { { "$expand", expandClause }, { "$select", selectClause } }).ParseSelectAndExpand(); ODataResourceTypeContext typeContext = ODataResourceTypeContext.Create(/*serializationInfo*/ null, this.citySet, this.cityType, this.cityType, true); ODataContextUrlInfo info = ODataContextUrlInfo.Create(typeContext, true, new ODataUri() { SelectAndExpand = selectExpandClause }); Uri contextUrl = this.responseContextUriBuilder.BuildContextUri(ODataPayloadKind.ResourceSet, info); return(contextUrl); }
private Uri CreateFeedContextUri(string applyClauseString) { ApplyClause applyClause = new ODataQueryOptionParser(edmModel, this.cityType, this.citySet, new Dictionary <string, string> { { "$apply", applyClauseString } }).ParseApply(); ODataResourceTypeContext typeContext = ODataResourceTypeContext.Create(/*serializationInfo*/ null, this.citySet, this.cityType, this.cityType, true); ODataContextUrlInfo info = ODataContextUrlInfo.Create(typeContext, false, new ODataUri() { Apply = applyClause }); Uri contextUrl = this.responseContextUriBuilder.BuildContextUri(ODataPayloadKind.ResourceSet, info); return(contextUrl); }
/// <summary> /// Create a ApplyFilterClause from a parse transformation query /// </summary> /// <param name="apply"></param> /// <param name="query"></param> /// <param name="oDataUriParserConfiguration"></param> /// <param name="edmType"></param> /// <param name="edmNavigationSource"></param> /// <returns></returns> private static ApplyFilterClause ParseFilter(ApplyClause apply, string query, ODataUriParserConfiguration oDataUriParserConfiguration, IEdmType edmType, IEdmNavigationSource edmNavigationSource) { query = IsolateQuery(query, UriQueryConstants.FilterTransformation); return(new ApplyFilterClause() { Apply = apply, Filter = ODataQueryOptionParser.ParseFilterImplementation( query, oDataUriParserConfiguration, edmType, edmNavigationSource), RawQueryString = query }); }
/// <summary> /// Initializes a new instance of the <see cref="ODataQueryOptions"/> class based on the incoming request and some metadata information from /// the <see cref="ODataQueryContext"/>. /// </summary> /// <param name="context">The <see cref="ODataQueryContext"/> which contains the <see cref="IEdmModel"/> and some type information.</param> private void Initialize(ODataQueryContext context) { Contract.Assert(context != null); ODataUriResolver uriResolver = null; if (context.RequestContainer != null) { uriResolver = context.RequestContainer.GetService <ODataUriResolver>(); } if (uriResolver != null) { _enableNoDollarSignQueryOptions = uriResolver.EnableNoDollarQueryOptions; } else { // Use the global setting _enableNoDollarSignQueryOptions = context.Request.IsNoDollarQueryEnable(); } // Parse the query from request Uri, including only keys which are OData query parameters or parameter alias // OData query parameters are normalized with the $-sign prefixes when the // <code>EnableNoDollarSignPrefixSystemQueryOption</code> option is used. RawValues = new ODataRawQueryOptions(); IDictionary <string, string> normalizedQueryParameters = GetODataQueryParameters(); _queryOptionParser = new ODataQueryOptionParser( context.Model, context.ElementType, context.NavigationSource, normalizedQueryParameters); if (uriResolver != null) { _queryOptionParser.Resolver = uriResolver; } else { // By default, let's enable the property name case-insensitive _queryOptionParser.Resolver = new ODataUriResolver { EnableCaseInsensitive = true }; } BuildQueryOptions(normalizedQueryParameters); Validator = ODataQueryValidator.GetODataQueryValidator(context); }
public void CopyConstructorShouldCopyAll() { this.settings.MetadataSelector = new TestMetadataSelector() { PropertyToOmit = "TestProperty" }; this.settings.SetContentType("application/json,application/atom+xml", "iso-8859-5, unicode-1-1;q=0.8"); this.settings.SetServiceDocumentUri(new Uri("http://example.com")); this.settings.ArrayPool = new TestCharArrayPool(5); this.settings.EnableMessageStreamDisposal = false; this.settings.EnableCharactersCheck = true; var edmModel = new EdmModel(); var defaultContainer = new EdmEntityContainer("TestModel", "DefaultContainer"); edmModel.AddElement(defaultContainer); var cityType = new EdmEntityType("TestModel", "City"); var cityIdProperty = cityType.AddStructuralProperty("Id", EdmCoreModel.Instance.GetInt32(/*isNullable*/ false)); cityType.AddKeys(cityIdProperty); cityType.AddStructuralProperty("Name", EdmCoreModel.Instance.GetString(/*isNullable*/ false)); cityType.AddStructuralProperty("Size", EdmCoreModel.Instance.GetInt32(/*isNullable*/ false)); edmModel.AddElement(cityType); var citySet = defaultContainer.AddEntitySet("Cities", cityType); var result = new ODataQueryOptionParser(edmModel, cityType, citySet, new Dictionary <string, string> { { "$expand", "" }, { "$select", "Id,*" } }).ParseSelectAndExpand(); this.settings.ODataUri = new ODataUri() { ServiceRoot = new Uri("http://test.org"), SelectAndExpand = result, Path = new ODataUriParser(edmModel, new Uri("http://test.org"), new Uri("http://test.org/Cities(1)/Name")).ParsePath() }; this.settings.LibraryCompatibility = ODataLibraryCompatibility.Version6; this.settings.Version = ODataVersion.V4; Func <string, bool> filter = name => true; this.settings.ShouldIncludeAnnotation = filter; var newSetting = this.settings.Clone(); var differences = ValidationHelper.GetDifferences <ODataMessageWriterSettings>(this.settings, newSetting); Assert.True(differences.Count == 0, String.Join(",", differences)); }
private static void TestCaseInsensitive() { Console.WriteLine("TestCaseInsensitive"); var parser = new ODataUriParser( extModel.Model, ServiceRoot, new Uri("http://demo/odata.svc/People(1)/Pets/TestNS.Fish?$orderby=Color")); var path = parser.ParsePath(); var clause = parser.ParseOrderBy(); Console.WriteLine(path.ToLogString()); Console.WriteLine(clause.Expression.ToLogString()); var parser2 = new ODataUriParser( extModel.Model, ServiceRoot, new Uri("http://demo/odata.svc/people(1)/pets/testns.fish?$ORDERBY=color")) { Resolver = new ODataUriResolver { EnableCaseInsensitive = true } }; // Identical to path and clause var path2 = parser2.ParsePath(); var clause2 = parser2.ParseOrderBy(); Console.WriteLine(path2.ToLogString()); Console.WriteLine(clause2.Expression.ToLogString()); // Query option parser also supports custom resolver var parser3 = new ODataQueryOptionParser( extModel.Model, extModel.Fish, extModel.PetSet, new Dictionary <string, string> { { "$orderby", "color" } }) { Resolver = new ODataUriResolver { EnableCaseInsensitive = true } }; var clause3 = parser3.ParseOrderBy(); Console.WriteLine(clause3.Expression.ToLogString()); }
private QueryNode TranslateFilterExpression(string filter) { var parser = new ODataQueryOptionParser(_model, _customerEntityType, _customersEntitySet, new Dictionary <string, string> { { "$filter", filter } }); FilterClause filterClause = parser.ParseFilter(); var translator = new ParameterAliasNodeTranslator( new Dictionary <string, SingleValueNode> { { "@p", _parameterAliasMappedNode } }); QueryNode translatedNode = filterClause.Expression.Accept(translator); return(translatedNode); }
/// <summary> /// Initializes a new instance of the <see cref="ApplyQueryOption"/> class. /// </summary> /// <param name="context">The OData query context.</param> /// <param name="queryOptionParser">The OData parser.</param> public ApplyQueryOption(ODataQueryContext context, ODataQueryOptionParser queryOptionParser) { if (context == null) { throw Error.ArgumentNull("context"); } if (queryOptionParser == null) { throw Error.ArgumentNull("queryOptionParser"); } this.Context = context; this._queryOptionParser = queryOptionParser; }
private void ParseAndExtract(string expandClauseText = null, string selectClauseText = null, string expectedExpandClauseFromOM = null, string expectedSelectClauseFromOM = null) { foreach (ODataVersion version in new ODataVersion[] { ODataVersion.V4, ODataVersion.V401 }) { var expandClause = new ODataQueryOptionParser(this.model, this.baseType, this.entitySet, new Dictionary <string, string> { { "$expand", expandClauseText }, { "$select", selectClauseText } }).ParseSelectAndExpand(); // Verify that the extension method gets the same result as the path extractor. string selectTextFromOM, expandTextFromOM; expandClause.GetSelectExpandPaths(version, out selectTextFromOM, out expandTextFromOM); selectTextFromOM.Should().Be(expectedSelectClauseFromOM ?? (selectClauseText ?? string.Empty)); expandTextFromOM.Should().Be(expectedExpandClauseFromOM ?? (expandClauseText ?? string.Empty)); } }
public void DuplicatedSelectPathInOneDollarSelectThrows(string select, string error) { // Arrange ODataQueryOptionParser parser = new ODataQueryOptionParser(_model.Model, _model.Customer, _model.Customers, new Dictionary <string, string> { { "$select", select } }); // Act Action test = () => parser.ParseSelectAndExpand(); // Assert ExceptionAssert.Throws <ODataException>(test, String.Format("Found mutliple select terms with same select path '{0}' at one $select, please combine them together.", error)); }
public void ApplyTo_Returns_Correct_Queryable(string filter, List <Dictionary <string, object> > aggregation) { // Arrange var model = new ODataModelBuilder() .Add_Order_EntityType() .Add_Customer_EntityType_With_Address() .Add_CustomerOrders_Relationship() .Add_Customer_EntityType_With_CollectionProperties() .Add_Customers_EntitySet() .GetEdmModel(); var context = new ODataQueryContext(model, typeof(Customer)) { RequestContainer = new MockContainer() }; var queryOptionParser = new ODataQueryOptionParser( context.Model, context.ElementType, context.NavigationSource, new Dictionary <string, string> { { "$apply", filter } }); var applyOption = new ApplyQueryOption(filter, context, queryOptionParser); IEnumerable <Customer> customers = CustomerApplyTestData; // Act IQueryable queryable = applyOption.ApplyTo(customers.AsQueryable(), new ODataQuerySettings { HandleNullPropagation = HandleNullPropagationOption.True }); // Assert Assert.NotNull(queryable); var actualCustomers = Assert.IsAssignableFrom <IEnumerable <DynamicTypeWrapper> >(queryable).ToList(); Assert.Equal(aggregation.Count(), actualCustomers.Count()); var aggEnum = actualCustomers.GetEnumerator(); foreach (var expected in aggregation) { aggEnum.MoveNext(); var agg = aggEnum.Current; foreach (var key in expected.Keys) { object value = GetValue(agg, key); Assert.Equal(expected[key], value); } } }
private static QueryClause CreateQueryClause(string query, IEdmModel model, Type type) { IEdmEntityType entityType = model.SchemaElements.OfType <IEdmEntityType>().Single(t => t.Name == type.Name); Assert.NotNull(entityType); // Guard IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Customers"); Assert.NotNull(entitySet); // Guard string[] queryItems = query.Split('&'); Dictionary <string, string> queries = new Dictionary <string, string>(); foreach (string item in queryItems) { if (item.StartsWith("$select=", StringComparison.Ordinal)) { queries["$select"] = item.Substring(8); } else if (item.StartsWith("$expand=", StringComparison.Ordinal)) { queries["$expand"] = item.Substring(8); } else if (item.StartsWith("$filter=", StringComparison.Ordinal)) { queries["$filter"] = item.Substring(8); } else if (item.StartsWith("$orderby=", StringComparison.Ordinal)) { queries["$orderby"] = item.Substring(9); } else if (item.StartsWith("$compute=", StringComparison.Ordinal)) { queries["$compute"] = item.Substring(9); } } ODataQueryOptionParser parser = new ODataQueryOptionParser(model, entityType, entitySet, queries); return(new QueryClause { Filter = parser.ParseFilter(), OrderBy = parser.ParseOrderBy(), SelectExpand = parser.ParseSelectAndExpand(), Compute = parser.ParseCompute() }); }
internal void AddAutoSelectExpandProperties() { bool containsAutoSelectExpandProperties = false; var autoExpandRawValue = GetAutoExpandRawValue(); var autoSelectRawValue = GetAutoSelectRawValue(); IDictionary <string, string> queryParameters = GetODataQueryParameters(); if (!String.IsNullOrEmpty(autoExpandRawValue) && !autoExpandRawValue.Equals(RawValues.Expand, StringComparison.Ordinal)) { queryParameters["$expand"] = autoExpandRawValue; containsAutoSelectExpandProperties = true; } else { autoExpandRawValue = RawValues.Expand; } if (!String.IsNullOrEmpty(autoSelectRawValue) && !autoSelectRawValue.Equals(RawValues.Select, StringComparison.Ordinal)) { queryParameters["$select"] = autoSelectRawValue; containsAutoSelectExpandProperties = true; } else { autoSelectRawValue = RawValues.Select; } if (containsAutoSelectExpandProperties) { _queryOptionParser = new ODataQueryOptionParser( Context.Model, Context.ElementType, Context.NavigationSource, queryParameters, Context.RequestContainer); // the Context.RequestContainer could be null for non-edm model var originalSelectExpand = SelectExpand; SelectExpand = new SelectExpandQueryOption( autoSelectRawValue, autoExpandRawValue, Context, _queryOptionParser); if (originalSelectExpand != null && originalSelectExpand.LevelsMaxLiteralExpansionDepth > 0) { SelectExpand.LevelsMaxLiteralExpansionDepth = originalSelectExpand.LevelsMaxLiteralExpansionDepth; } } }
/// <summary> /// Initializes a new instance of the <see cref="ODataQueryOptions"/> class based on the incoming request and some metadata information from /// the <see cref="ODataQueryContext"/>. /// </summary> /// <param name="context">The <see cref="ODataQueryContext"/> which contains the <see cref="IEdmModel"/> and some type information.</param> /// <param name="request">The incoming request message.</param> public ODataQueryOptions(ODataQueryContext context, HttpRequestMessage request) { if (context == null) { throw Error.ArgumentNull("context"); } if (request == null) { throw Error.ArgumentNull("request"); } if (request.GetConfiguration() != null) { _assembliesResolver = request.GetConfiguration().Services.GetAssembliesResolver(); } // fallback to the default assemblies resolver if none available. _assembliesResolver = _assembliesResolver ?? new DefaultAssembliesResolver(); // remember the context and request Context = context; Request = request; // Parse the query from request Uri RawValues = new ODataRawQueryOptions(); IDictionary <string, string> queryParameters = request.GetQueryNameValuePairs().ToDictionary(p => p.Key, p => p.Value); _queryOptionParser = new ODataQueryOptionParser( context.Model, context.ElementType, context.NavigationSource, queryParameters); HttpConfiguration configuration = Request.GetConfiguration(); if (configuration != null) { ODataUriResolverSetttings resolverSettings = configuration.GetResolverSettings(); _queryOptionParser.Resolver = resolverSettings.CreateResolver(context.Model); } BuildQueryOptions(queryParameters); Validator = new ODataQueryValidator(); }
private ApplyClause CreateApplyNode(string clause, IEdmModel model, Type entityType) { IEdmEntityType productType = model.SchemaElements.OfType <IEdmEntityType>().Single(t => t.Name == entityType.Name); Assert.NotNull(productType); // Guard IEdmEntitySet products = model.EntityContainer.FindEntitySet("Products"); Assert.NotNull(products); // Guard ODataQueryOptionParser parser = new ODataQueryOptionParser(model, productType, products, new Dictionary <string, string> { { "$apply", clause } }); return(parser.ParseApply()); }
private static FilterClause CreateFilterClause(string filter, IEdmModel model, Type type) { IEdmEntityType entityType = model.SchemaElements.OfType <IEdmEntityType>().Single(t => t.Name == type.Name); Assert.NotNull(entityType); // Guard IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Products"); Assert.NotNull(entitySet); // Guard ODataQueryOptionParser parser = new ODataQueryOptionParser(model, entityType, entitySet, new Dictionary <string, string> { { "$filter", filter } }); return(parser.ParseFilter()); }
/// <summary> /// Apply $top and $skip parameters to query. /// </summary> /// <typeparam name="T">The type param</typeparam> /// <param name="query">The OData aware query.</param> /// <param name="topText">$top parameter value</param> /// <param name="skipText">$skip parameter value</param> /// <param name="entitySetName">The entity set name.</param> /// <returns>The <see cref="ODataQuery{T}"/> query with applied $top and $skip parameters.</returns> public static ODataQuery <T> TopSkip <T>(this ODataQuery <T> query, string topText = null, string skipText = null, string entitySetName = null) { if (query == null) { throw new ArgumentNullException(nameof(query)); } ODataSettings settings = query.ServiceProvider.GetRequiredService <ODataSettings>(); Dictionary <string, string> dictionary = new Dictionary <string, string>(); if (topText != null) { dictionary.Add("$top", topText); } if (skipText != null) { dictionary.Add("$skip", skipText); } ODataQueryOptionParser queryOptionParser = GetParser( query, entitySetName, dictionary); long?skip = queryOptionParser.ParseSkip(); long?top = queryOptionParser.ParseTop(); if (skip.HasValue || top.HasValue || settings.QuerySettings.PageSize.HasValue) { IQueryable <T> result = TopSkipHelper.ApplySkipWithValidation(query, skip, settings); if (top.HasValue) { result = TopSkipHelper.ApplyTopWithValidation(result, top, settings); } else { result = TopSkipHelper.ApplyTopWithValidation(result, settings.QuerySettings.PageSize, settings); } return(new ODataQuery <T>(result, query.ServiceProvider)); } return(query); }
private static void GetGroupByParams(string value, out IQueryable data, out ODataQueryContext context, out ODataQuerySettings settings, out ApplyGroupbyClause groupByClause, out DefaultAssembliesResolver assembliesResolver, out GroupByImplementation groupByImplementation, out Type keyType, out IEnumerable <LambdaExpression> propertiesToGroupByExpressions) { string queryOption = "$apply"; data = TestDataSource.CreateData(); settings = new ODataQuerySettings() { PageSize = 2000, HandleNullPropagation = HandleNullPropagationOption.False }; var _settings = settings; var model = TestModelBuilder.CreateModel(new Type[] { typeof(Category), typeof(Product), typeof(Sales) }); context = new ODataQueryContext(model, typeof(Sales), new ODataPath(new ODataPathSegment[] { new EntitySetPathSegment("Sales") })); var _context = context; IEdmNavigationSource source = model.FindDeclaredEntitySet("Sales"); var parser = new ODataQueryOptionParser(model, model.FindDeclaredType("System.Web.OData.Aggregation.Tests.Common.Sales"), source, new Dictionary <string, string>() { { queryOption, value } }); var applyCaluse = parser.ParseApply(); groupByClause = applyCaluse.Transformations.First().Item2 as ApplyGroupbyClause; assembliesResolver = new DefaultAssembliesResolver(); var _assembliesResolver = assembliesResolver; groupByImplementation = new GroupByImplementation() { Context = context }; keyType = groupByImplementation.GetGroupByKeyType(groupByClause); var entityParam = Expression.Parameter(context.ElementClrType, "$it"); propertiesToGroupByExpressions = groupByClause.SelectedPropertiesExpressions.Select( exp => FilterBinder.Bind(exp, _context.ElementClrType, _context.Model, _assembliesResolver, _settings, entityParam)); }
public static ODataQueryOptionParser GetParser <T>(ODataQuery <T> query, string entitySetName, IDictionary <string, string> raws) { IEdmModel edmModel = query.EdmModel; if (entitySetName == null) { entitySetName = typeof(T).Name; } IEdmEntityContainer[] containers = edmModel.SchemaElements.Where( e => e.SchemaElementKind == EdmSchemaElementKind.EntityContainer && (e as IEdmEntityContainer).FindEntitySet(entitySetName) != null) .OfType <IEdmEntityContainer>() .ToArray(); if (containers.Length == 0) { throw new ArgumentException($"Unable to find {entitySetName} entity set in the model.", nameof(entitySetName)); } if (containers.Length > 1) { throw new ArgumentException($"Entity Set {entitySetName} found more that 1 time", nameof(entitySetName)); } IEdmEntitySet entitySet = containers.Single().FindEntitySet(entitySetName); if (entitySet == null) { } ODataPath path = new ODataPath(new EntitySetSegment(entitySet)); ODataQueryOptionParser parser = new ODataQueryOptionParser(edmModel, path, raws, query.ServiceProvider); ODataSettings settings = query.ServiceProvider.GetRequiredService <ODataSettings>(); // Workaround for strange behavior in QueryOptionsParserConfiguration constructor which set it to false always parser.Resolver.EnableCaseInsensitive = settings.EnableCaseInsensitive; return(parser); }
/// <summary> /// Initializes a new instance of the <see cref="ODataQueryOptions"/> class based on the incoming request and some metadata information from /// the <see cref="ODataQueryContext"/>. /// </summary> /// <param name="context">The <see cref="ODataQueryContext"/> which contains the <see cref="IEdmModel"/> and some type information.</param> /// <param name="request">The incoming request message.</param> public ODataQueryOptions(ODataQueryContext context, HttpRequestMessage request) { if (context == null) { throw Error.ArgumentNull("context"); } if (request == null) { throw Error.ArgumentNull("request"); } // Set the request container into context Contract.Assert(context.RequestContainer == null); context.RequestContainer = request.GetRequestContainer(); // Remember the context and request Context = context; Request = request; ODataUriResolver uriResolver = request.GetRequestContainer().GetRequiredService <ODataUriResolver>(); if (uriResolver != null) { _enableNoDollarSignQueryOptions = uriResolver.EnableNoDollarQueryOptions; } // Parse the query from request Uri, including only keys which are OData query parameters or parameter alias // OData query parameters are normalized with the $-sign prefixes when the // <code>EnableNoDollarSignPrefixSystemQueryOption</code> option is used. RawValues = new ODataRawQueryOptions(); IDictionary <string, string> normalizedqueryParameters = GetODataQueryParameters(); _queryOptionParser = new ODataQueryOptionParser( context.Model, context.ElementType, context.NavigationSource, normalizedqueryParameters); _queryOptionParser.Resolver = uriResolver; BuildQueryOptions(normalizedqueryParameters); Validator = ODataQueryValidator.GetODataQueryValidator(context); }
private static OrderByClause TranslateParameterAlias(OrderByClause orderBy, ODataQueryOptionParser queryOptionParser) { if (orderBy == null) { return(null); } SingleValueNode orderByExpression = orderBy.Expression.Accept( new ParameterAliasNodeTranslator(queryOptionParser.ParameterAliasNodes)) as SingleValueNode; orderByExpression = orderByExpression ?? new ConstantNode(null, "null"); return(new OrderByClause( TranslateParameterAlias(orderBy.ThenBy, queryOptionParser), orderByExpression, orderBy.Direction, orderBy.RangeVariable)); }
public IEnumerable <ProductDTO> Get(ODataQueryOptions <ProductDTO> q) { IQueryable <Product> products = this._products.AsQueryable(); IEdmModel model = GetModel(); IEdmType type = model.FindDeclaredType("TestAPI.Models.Product"); IEdmNavigationSource source = model.FindDeclaredEntitySet("Products"); ODataQueryOptionParser parser = new ODataQueryOptionParser(model, type, source, new Dictionary <string, string> { { "$filter", q.Filter.RawValue } }); ODataQueryContext context = new ODataQueryContext(model, typeof(Product), q.Context.Path); FilterQueryOption filter = new FilterQueryOption(q.Filter.RawValue, context, parser); if (filter != null) { products = filter.ApplyTo(products, new ODataQuerySettings()) as IQueryable <Product>; } return(products.Select(p => new ProductDTO(p))); }
private FilterClause CreateFilterClause(string filterExpression) { const string uriBase = "http://service/"; Uri uri = new Uri(uriBase + "Pet1Set?$filter=" + filterExpression); ODataUriParser parser = new ODataUriParser(HardCodedTestModel.TestModel, new Uri(uriBase), uri); IEdmEntitySet entitySet = HardCodedTestModel.GetPet1Set(); Dictionary <string, string> queryOptions = new Dictionary <string, string>() { { "$filter", filterExpression } }; // Use query option parser to help create the filter because it takes care of a bunch of instantiations ODataQueryOptionParser queryOptionParser = new ODataQueryOptionParser(HardCodedTestModel.TestModel, entitySet.EntityType(), entitySet, queryOptions); return(queryOptionParser.ParseFilter()); }
public void CreatePropertyValueExpressionWithFilter_Collection_Works_HandleNullPropagationOptionIsTrue() { // Arrange _model.Model.SetAnnotationValue(_model.Order, new ClrTypeAnnotation(typeof(Order))); _settings.HandleNullPropagation = HandleNullPropagationOption.True; var customer = Expression.Constant(new Customer { Orders = new[] { new Order { ID = 1 }, new Order { ID = 2 } } }); var ordersProperty = _model.Customer.NavigationProperties().Single(p => p.Name == "Orders"); var parser = new ODataQueryOptionParser( _model.Model, _model.Order, _model.Orders, new Dictionary <string, string> { { "$filter", "ID eq 1" } }); var filterCaluse = parser.ParseFilter(); // Act var filterInExpand = _binder.CreatePropertyValueExpressionWithFilter( _model.Customer, ordersProperty, customer, filterCaluse); // Assert Assert.Equal( string.Format( "IIF((value({0}) == null), null, IIF((value({0}).Orders == null), null, " + "value({0}).Orders.AsQueryable().Where($it => ($it.ID == value({1}).TypedProperty))))", customer.Type, "Microsoft.AspNet.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.Int32]"), filterInExpand.ToString()); var orders = Expression.Lambda(filterInExpand).Compile().DynamicInvoke() as IEnumerable <Order>; Assert.Single(orders); Assert.Equal(1, orders.ToList()[0].ID); }
[InlineData("NS.*", null, true, "specialUpgrade,upgrade")] // select wild card actions -> select all public void GetActionsToBeSelected_Selects_ExpectedActions( string select, string expand, bool specialCustomer, string actionsToSelect) { // Arrange ODataQueryOptionParser parser = new ODataQueryOptionParser(_model.Model, _model.Customer, _model.Customers, new Dictionary <string, string> { { "$select", select }, { "$expand", expand } }); SelectExpandClause selectExpandClause = parser.ParseSelectAndExpand(); IEdmEntityType entityType = specialCustomer ? _model.SpecialCustomer : _model.Customer; // Act SelectExpandNode selectExpandNode = new SelectExpandNode(selectExpandClause, entityType, _model.Model); var result = selectExpandNode.SelectedActions; // Assert Assert.Equal(actionsToSelect, String.Join(",", result.Select(p => p.Name).OrderBy(n => n))); }
public void CreatePropertyValueExpressionWithFilter_ThrowsODataException_IfMappingTypeIsNotFoundInModel() { // Arrange _model.Model.SetAnnotationValue <ClrTypeAnnotation>(_model.Order, value: null); var customer = Expression.Constant(new Customer()); var ordersProperty = _model.Customer.NavigationProperties().Single(p => p.Name == "Orders"); var parser = new ODataQueryOptionParser( _model.Model, _model.Order, _model.Orders, new Dictionary <string, string> { { "$filter", "ID eq 1" } }); var filterCaluse = parser.ParseFilter(); // Act & Assert Assert.Throws <ODataException>( () => _binder.CreatePropertyValueExpressionWithFilter(_model.Customer, ordersProperty, customer, filterCaluse), "The provided mapping does not contain an entry for the entity type 'NS.Order'."); }
/// <summary> /// Initialize a new instance of <see cref="FilterQueryOption"/> based on the raw $filter value and /// an EdmModel from <see cref="ODataQueryContext"/>. /// </summary> /// <param name="rawValue">The raw value for $filter query. It can be null or empty.</param> /// <param name="context">The <see cref="ODataQueryContext"/> which contains the <see cref="IEdmModel"/> and some type information</param> /// <param name="queryOptionParser">The <see cref="ODataQueryOptionParser"/> which is used to parse the query option.</param> public FilterQueryOption(string rawValue, ODataQueryContext context, ODataQueryOptionParser queryOptionParser) { if (context == null) { throw Error.ArgumentNull("context"); } if (String.IsNullOrEmpty(rawValue)) { throw Error.ArgumentNullOrEmpty("rawValue"); } if (queryOptionParser == null) { throw Error.ArgumentNull("queryOptionParser"); } Context = context; RawValue = rawValue; _queryOptionParser = queryOptionParser; }
public void ProjectAsWrapper_Element_ProjectedValueDoesNotContainInstance_IfSelectionIsPartial() { // Arrange Customer customer = new Customer(); ODataQueryOptionParser parser = new ODataQueryOptionParser(_model.Model, _model.Customer, _model.Customers, new Dictionary <string, string> { { "$select", "ID,Orders" }, { "$expand", "Orders" } }); SelectExpandClause selectExpand = parser.ParseSelectAndExpand(); Expression source = Expression.Constant(customer); // Act Expression projection = _binder.ProjectAsWrapper(source, selectExpand, _model.Customer, _model.Customers); // Assert Assert.Equal(ExpressionType.MemberInit, projection.NodeType); Assert.NotEmpty((projection as MemberInitExpression).Bindings.Where(p => p.Member.Name == "Instance")); SelectExpandWrapper <Customer> customerWrapper = Expression.Lambda(projection).Compile().DynamicInvoke() as SelectExpandWrapper <Customer>; Assert.Same(customer, customerWrapper.Instance); }
public void GetPropertiesToBeSelected_Selects_ExpectedProperties_OnExpandedOrders( string select, string expand, bool specialOrder, string structuralPropertiesToSelect) { // Arrange ODataQueryOptionParser parser = new ODataQueryOptionParser(_model.Model, _model.Customer, _model.Customers, new Dictionary <string, string> { { "$select", select }, { "$expand", expand } }); SelectExpandClause selectExpandClause = parser.ParseSelectAndExpand(); SelectExpandClause nestedSelectExpandClause = selectExpandClause.SelectedItems.OfType <ExpandedNavigationSelectItem>().Single().SelectAndExpand; IEdmEntityType entityType = specialOrder ? _model.SpecialOrder : _model.Order; // Act SelectExpandNode selectExpandNode = new SelectExpandNode(nestedSelectExpandClause, entityType, _model.Model); var result = selectExpandNode.SelectedStructuralProperties; // Assert Assert.Equal(structuralPropertiesToSelect, String.Join(",", result.Select(p => p.Name).OrderBy(n => n))); }
public void ProjectAsWrapper_Element_ProjectedValueContains_SelectedStructuralProperties() { // Arrange Customer customer = new Customer { Name = "OData" }; ODataQueryOptionParser parser = new ODataQueryOptionParser(_model.Model, _model.Customer, _model.Customers, new Dictionary <string, string> { { "$select", "Name,Orders" }, { "$expand", "Orders" } }); SelectExpandClause selectExpand = parser.ParseSelectAndExpand(); Expression source = Expression.Constant(customer); // Act Expression projection = _binder.ProjectAsWrapper(source, selectExpand, _model.Customer, _model.Customers); // Assert SelectExpandWrapper <Customer> customerWrapper = Expression.Lambda(projection).Compile().DynamicInvoke() as SelectExpandWrapper <Customer>; Assert.Equal(customer.Name, customerWrapper.Container.ToDictionary(new IdentityPropertyMapper())["Name"]); }