public void GetETag_Returns_ETagInHeader_ForInteger(byte byteValue, short shortValue, long longValue)
        {
            // Arrange
            Dictionary <string, object> properties = new Dictionary <string, object>
            {
                { "ByteVal", byteValue },
                { "LongVal", longValue },
                { "ShortVal", shortValue }
            };
            EntityTagHeaderValue etagHeaderValue = new DefaultODataETagHandler().CreateETag(properties);

            var builder = ODataConventionModelBuilderFactory.Create();

            builder.EntitySet <MyEtagOrder>("Orders");
            IEdmModel          model     = builder.GetEdmModel();
            IEdmEntitySet      orders    = model.FindDeclaredEntitySet("Orders");
            ODataPath          odataPath = new ODataPath(new EntitySetSegment(orders));
            HttpRequestMessage request   = new HttpRequestMessage();

            request.EnableHttpDependencyInjectionSupport(model);
            request.ODataProperties().Path = odataPath;

            // Act
            ETag    result        = request.GetETag(etagHeaderValue);
            dynamic dynamicResult = result;

            // Assert
            byte actualByte = Assert.IsType <byte>(result["ByteVal"]);

            Assert.Equal(actualByte, dynamicResult.ByteVal);
            Assert.Equal(byteValue, actualByte);

            short actualShort = Assert.IsType <short>(result["ShortVal"]);

            Assert.Equal(actualShort, dynamicResult.ShortVal);
            Assert.Equal(shortValue, actualShort);

            long actualLong = Assert.IsType <long>(result["LongVal"]);

            Assert.Equal(actualLong, dynamicResult.LongVal);
            Assert.Equal(longValue, actualLong);
        }
示例#2
0
        public async Task EnableNestedPaths_ReturnsSingleton()
        {
            // Arrange
            string url = $"{_baseUrl}EnableNestedPathsTopCustomer";

            // Act
            HttpResponseMessage response = await _client.GetAsync(url);

            var stream = await response.Content.ReadAsStreamAsync();

            var singleton    = _model.EntityContainer.FindSingleton("EnableNestedPathsTopCustomer");
            var path         = new ODataPath(new SingletonSegment(singleton));
            var readCustomer = ReadSingleResponse <EnableNestedPathsCustomer>(stream, _model, path);

            // Assert
            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
            Assert.Equal(_db.Customers.First(),
                         readCustomer,
                         new EnableNestedPathsCustomerComparer());
        }
        /// <summary>
        /// Selects the controller for OData requests.
        /// </summary>
        /// <param name="odataPath">The OData path.</param>
        /// <returns>
        ///   <c>null</c> if the request isn't handled by this convention; otherwise, the name of the selected controller
        /// </returns>
        internal static SelectControllerResult SelectControllerImpl(Microsoft.AspNet.OData.Routing.ODataPath odataPath)
        {
            // entity set
            EntitySetSegment entitySetSegment = odataPath.Segments.FirstOrDefault() as EntitySetSegment;

            if (entitySetSegment != null)
            {
                return(new SelectControllerResult(entitySetSegment.EntitySet.Name, null));
            }

            // singleton
            SingletonSegment singletonSegment = odataPath.Segments.FirstOrDefault() as SingletonSegment;

            if (singletonSegment != null)
            {
                return(new SelectControllerResult(singletonSegment.Singleton.Name, null));
            }

            return(null);
        }
示例#4
0
        public async Task EnableNestedPaths_ReturnsPropertyOfSingleton()
        {
            // Arrange
            string url = $"{_baseUrl}EnableNestedPathsTopCustomer/FavoriteProduct";

            // Act
            HttpResponseMessage response = await _client.GetAsync(url);

            var stream = await response.Content.ReadAsStreamAsync();

            var entitySet   = _model.EntityContainer.FindEntitySet("EnableNestedPathsProducts");
            var path        = new ODataPath(new EntitySetSegment(entitySet));
            var readProduct = ReadSingleResponse <EnableNestedPathsProduct>(stream, _model, path);

            // Assert
            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
            Assert.Equal(_db.Customers.First().FavoriteProduct,
                         readProduct,
                         new EnableNestedPathsProductComparer());
        }
        /// <inheritdoc/>
        /// <remarks>This signature uses types that are AspNetCore-specific.</remarks>
        public IEnumerable <ControllerActionDescriptor> SelectAction(RouteContext routeContext)
        {
            if (routeContext == null)
            {
                throw new ArgumentNullException("routeContext");
            }

            Microsoft.AspNet.OData.Routing.ODataPath odataPath = routeContext.HttpContext.ODataFeature().Path;
            if (odataPath == null)
            {
                throw new ArgumentNullException("odataPath");
            }

            HttpRequest request = routeContext.HttpContext.Request;

            SelectControllerResult controllerResult = SelectControllerImpl(odataPath);

            if (controllerResult != null)
            {
                // Get a IActionDescriptorCollectionProvider from the global service provider.
                IActionDescriptorCollectionProvider actionCollectionProvider =
                    routeContext.HttpContext.RequestServices.GetRequiredService <IActionDescriptorCollectionProvider>();
                Contract.Assert(actionCollectionProvider != null);

                IEnumerable <ControllerActionDescriptor> actionDescriptors = actionCollectionProvider
                                                                             .ActionDescriptors.Items.OfType <ControllerActionDescriptor>()
                                                                             .Where(c => c.AttributeRouteInfo != null && c.AttributeRouteInfo.Template == controllerResult.ControllerName);

                if (actionDescriptors != null)
                {
                    string actionName = SelectAction(routeContext, controllerResult, actionDescriptors);
                    if (!String.IsNullOrEmpty(actionName))
                    {
                        return(actionDescriptors.Where(
                                   c => String.Equals(c.ActionName, actionName, StringComparison.OrdinalIgnoreCase)));
                    }
                }
            }

            return(null);
        }
示例#6
0
        public RestierQueryBuilder(ApiBase api, ODataPath path)
        {
            Ensure.NotNull(api, nameof(api));
            Ensure.NotNull(path, nameof(path));
            this.api  = api;
            this.path = path;

            handlers[typeof(EntitySetSegment)]          = HandleEntitySetPathSegment;
            handlers[typeof(SingletonSegment)]          = HandleSingletonPathSegment;
            handlers[typeof(OperationSegment)]          = EmptyHandler;
            handlers[typeof(OperationImportSegment)]    = EmptyHandler;
            handlers[typeof(CountSegment)]              = HandleCountPathSegment;
            handlers[typeof(ValueSegment)]              = HandleValuePathSegment;
            handlers[typeof(KeySegment)]                = HandleKeyValuePathSegment;
            handlers[typeof(NavigationPropertySegment)] = HandleNavigationPathSegment;
            handlers[typeof(PropertySegment)]           = HandlePropertyAccessPathSegment;
            handlers[typeof(TypeSegment)]               = HandleEntityTypeSegment;

            // Complex cast is not supported by EF, and is not supported here
            // this.handlers[ODataSegmentKinds.ComplexCast] = null;
        }
        public void Constructor_TakingClrTypeAndPath_SetsProperties()
        {
            // Arrange
            ODataModelBuilder odataModel = new ODataModelBuilder().Add_Customer_EntityType();
            string            setName    = typeof(Customer).Name;

            odataModel.EntitySet <Customer>(setName);
            IEdmModel      model      = odataModel.GetEdmModel();
            IEdmEntitySet  entitySet  = model.EntityContainer.FindEntitySet(setName);
            IEdmEntityType entityType = entitySet.EntityType();
            ODataPath      path       = new ODataPath(new EntitySetSegment(entitySet));

            // Act
            ODataQueryContext context = new ODataQueryContext(model, typeof(Customer), path);

            // Assert
            Assert.Same(model, context.Model);
            Assert.Same(entityType, context.ElementType);
            Assert.Same(entitySet, context.NavigationSource);
            Assert.Same(typeof(Customer), context.ElementClrType);
        }
示例#8
0
        private static ODataDeserializer GetDeserializer(
            Type type,
            ODataPath path,
            IEdmModel model,
            Func <IEdmTypeReference, ODataDeserializer> getEdmTypeDeserializer,
            Func <Type, ODataDeserializer> getODataPayloadDeserializer,
            out IEdmTypeReference expectedPayloadType)
        {
            expectedPayloadType = EdmLibHelpers.GetExpectedPayloadType(type, path, model);

            // Get the deserializer using the CLR type first from the deserializer provider.
            ODataDeserializer deserializer = getODataPayloadDeserializer(type);

            if (deserializer == null && expectedPayloadType != null)
            {
                // we are in typeless mode, get the deserializer using the edm type from the path.
                deserializer = getEdmTypeDeserializer(expectedPayloadType);
            }

            return(deserializer);
        }
示例#9
0
 internal static IReadOnlyDictionary <string, object> GetPathKeyValues(ODataPath path)
 {
     if (path.PathTemplate == "~/entityset/key" ||
         path.PathTemplate == "~/entityset/key/cast")
     {
         var keySegment = (KeySegment)path.Segments[1];
         return(GetPathKeyValues(keySegment));
     }
     else if (path.PathTemplate == "~/entityset/cast/key")
     {
         var keySegment = (KeySegment)path.Segments[2];
         return(GetPathKeyValues(keySegment));
     }
     else
     {
         throw new InvalidOperationException(string.Format(
                                                 CultureInfo.InvariantCulture,
                                                 Resources.InvalidPathTemplateInRequest,
                                                 "~/entityset/key"));
     }
 }
        public void SelectExpandClause_Property_ApplyOnNavigationSource()
        {
            // Arrange
            IEdmModel model = _model.Model;

            _model.Model.SetAnnotationValue(_model.Customer, new ClrTypeAnnotation(typeof(Customer)));
            ODataPath         odataPath = new ODataPath(new EntitySetSegment(_model.Customers));
            ODataQueryContext context   = new ODataQueryContext(model, typeof(Customer), odataPath);

            context.RequestContainer = new MockContainer();
            SelectExpandQueryOption option = new SelectExpandQueryOption(null, "Orders($apply=aggregate($count as Count))", context);

            // Act
            SelectExpandClause selectExpandClause = option.SelectExpandClause;

            // Assert
            Assert.NotEmpty(selectExpandClause.SelectedItems.OfType <ExpandedNavigationSelectItem>());
            ExpandedNavigationSelectItem navigationItem = selectExpandClause.SelectedItems.OfType <ExpandedNavigationSelectItem>().Single();

            Assert.NotNull(navigationItem.ApplyOption);
        }
示例#11
0
        public IActionResult GetNavigation(string key, string navigation)
        {
            ODataPath path = Request.ODataFeature().Path;

            if (path.PathTemplate != "~/entityset/key/navigation")
            {
                return(BadRequest("Not the correct navigation property access request!"));
            }

            NavigationPropertySegment property = path.Segments.Last() as NavigationPropertySegment;

            if (property == null)
            {
                return(BadRequest("Not the correct navigation property access request!"));
            }

            IEdmEntityType entityType = property.NavigationProperty.DeclaringType as IEdmEntityType;

            EdmEntityObject entity = new EdmEntityObject(entityType);

            string sourceString = Request.GetDataSource();

            DataSourceProvider.Get(sourceString, key, entity);

            object value = DataSourceProvider.GetProperty(sourceString, navigation, entity);

            if (value == null)
            {
                return(NotFound());
            }

            IEdmEntityObject nav = value as IEdmEntityObject;

            if (nav == null)
            {
                return(NotFound());
            }

            return(Ok(nav));
        }
        public void GetETag_Returns_ETagInHeader_ForDouble(double value, bool isEqual)
        {
            // Arrange
            Dictionary <string, object> properties = new Dictionary <string, object> {
                { "Version", value }
            };
            EntityTagHeaderValue etagHeaderValue = new DefaultODataETagHandler().CreateETag(properties);

            var builder = ODataConventionModelBuilderFactory.Create();

            builder.EntitySet <MyEtagCustomer>("Customers");
            IEdmModel     model     = builder.GetEdmModel();
            IEdmEntitySet customers = model.FindDeclaredEntitySet("Customers");
            ODataPath     odataPath = new ODataPath(new EntitySetSegment(customers));

            HttpRequestMessage request = new HttpRequestMessage();

            request.EnableHttpDependencyInjectionSupport(model);
            request.ODataProperties().Path = odataPath;

            // Act
            ETag    result        = request.GetETag(etagHeaderValue);
            dynamic dynamicResult = result;

            // Assert
            double actual = Assert.IsType <double>(result["Version"]);

            Assert.Equal(actual, dynamicResult.Version);

            if (isEqual)
            {
                Assert.Equal(value, actual);
            }
            else
            {
                Assert.NotEqual(value, actual);

                Assert.True(actual - value < 0.0000001);
            }
        }
示例#13
0
        // Retrieves the IEdmEntityType from the path only in the case that we are addressing a single entity.
        // We iterate the path backwards and we return as soon as we realize we are referencing a single entity.
        // That is, as soon as we find a singleton segment, a key segment or a navigation segment with target
        // multiplicity 0..1 or 1.
        internal static IEdmEntityType GetSingleEntityEntityType(ODataPath path)
        {
            if (path == null || path.Segments.Count == 0)
            {
                return(null);
            }

            int currentSegmentIndex = path.Segments.Count - 1;

            // Skip a possible sequence of casts at the end of the path.
            while (currentSegmentIndex >= 0 &&
                   path.Segments[currentSegmentIndex] is TypeSegment)
            {
                currentSegmentIndex--;
            }
            if (currentSegmentIndex < 0)
            {
                return(null);
            }

            ODataPathSegment currentSegment = path.Segments[currentSegmentIndex];

            if (currentSegment is SingletonSegment || currentSegment is KeySegment)
            {
                return((IEdmEntityType)path.EdmType);
            }

            NavigationPropertySegment navigationPropertySegment = currentSegment as NavigationPropertySegment;

            if (navigationPropertySegment != null)
            {
                if (navigationPropertySegment.NavigationProperty.TargetMultiplicity() == EdmMultiplicity.ZeroOrOne ||
                    navigationPropertySegment.NavigationProperty.TargetMultiplicity() == EdmMultiplicity.One)
                {
                    return((IEdmEntityType)path.EdmType);
                }
            }

            return(null);
        }
        public void GenerateNavigationLink_WorksToGenerateExpectedNavigationLink_ForContainedNavigation(
            bool includeCast,
            string expectedNavigationLink)
        {
            // NOTE: This test is generating a link that does not technically correspond to a valid model (specifically
            //       the extra OrderLines navigation), but it allows us to validate the nested navigation scenario
            //       without twisting the model unnecessarily.

            // Arrange
            IEdmEntityType         myOrder            = (IEdmEntityType)_model.Model.FindDeclaredType("NS.MyOrder");
            IEdmNavigationProperty orderLinesProperty = myOrder.NavigationProperties().Single(x => x.ContainsTarget);

            IEdmEntitySet entitySet = _model.Model.FindDeclaredEntitySet(("MyOrders"));
            IDictionary <string, object> parameters = new Dictionary <string, object>
            {
                { "ID", 42 }
            };

            IDictionary <string, object> parameters2 = new Dictionary <string, object>
            {
                { "ID", 21 }
            };

            ODataPath path = new ODataPath(
                new EntitySetSegment(entitySet),
                new KeySegment(parameters.ToArray(), myOrder, entitySet),
                new NavigationPropertySegment(orderLinesProperty, _model.OrderLines),
                new KeySegment(parameters2.ToArray(), _model.OrderLine, _model.OrderLines));

            var request           = RequestFactory.CreateFromModel(_model.Model);
            var serializerContext = ODataSerializerContextFactory.Create(_model.Model, _model.OrderLines, path, request);
            var entityContext     = new ResourceContext(serializerContext, _model.OrderLine.AsReference(), new { ID = 21 });

            // Act
            Uri uri = entityContext.GenerateNavigationPropertyLink(orderLinesProperty, includeCast);

            // Assert
            Assert.Equal(expectedNavigationLink, uri.AbsoluteUri);
        }
 /// <inheritdoc/>
 protected override string SelectAction(string requestMethod, ODataPath odataPath, TestControllerContext controllerContext, IList <string> actionList)
 {
     if ((odataPath.PathTemplate == "~/entityset/key/navigation") || (odataPath.PathTemplate == "~/entityset/key/cast/navigation"))
     {
         NavigationPropertySegment segment            = odataPath.Segments.Last <ODataPathSegment>() as NavigationPropertySegment;
         IEdmNavigationProperty    navigationProperty = segment.NavigationProperty;
         IEdmEntityType            declaringType      = navigationProperty.DeclaringType as IEdmEntityType;
         if (declaringType != null)
         {
             string prefix = ODataHelper.GetHttpPrefix(requestMethod);
             if (string.IsNullOrEmpty(prefix))
             {
                 return(null);
             }
             KeySegment segment2 = odataPath.Segments[1] as KeySegment;
             controllerContext.AddKeyValueToRouteData(segment2);
             string key = prefix + navigationProperty.Name + "On" + declaringType.Name;
             return(actionList.Contains(key) ? key : (prefix + navigationProperty.Name));
         }
     }
     return(null);
 }
示例#16
0
        public async Task IEnumerableOfEntityTypeSerializesAsODataResourceSet()
        {
            // Arrange
            IEdmEntitySet entitySet = _model.EntityContainer.FindEntitySet("employees");
            ODataPath     path      = new ODataPath(new EntitySetSegment(entitySet));

            var request   = RequestFactory.CreateFromModel(_model, "http://localhost/property", "Route", path);
            var payload   = new ODataPayloadKind[] { ODataPayloadKind.ResourceSet };
            var formatter = FormatterTestHelper.GetFormatter(payload, request);

            IEnumerable <Employee> collectionOfPerson = new Collection <Employee>()
            {
                (Employee)TypeInitializer.GetInstance(SupportedTypes.Employee, 0),
                (Employee)TypeInitializer.GetInstance(SupportedTypes.Employee, 1),
            };

            var content = FormatterTestHelper.GetContent(collectionOfPerson, formatter,
                                                         ODataMediaTypes.ApplicationJsonODataMinimalMetadata);

            // Act & Assert
            JsonAssert.Equal(Resources.FeedOfEmployee, await FormatterTestHelper.GetContentResult(content, request));
        }
        public void GetETagTEntity_Returns_ETagInHeader()
        {
            // Arrange
            CustomersModelWithInheritance model = new CustomersModelWithInheritance();

            HttpRequestMessage request = new HttpRequestMessage();
            request.EnableHttpDependencyInjectionSupport(model.Model);

            Dictionary<string, object> properties = new Dictionary<string, object> { { "City", "Foo" } };
            EntityTagHeaderValue etagHeaderValue = new DefaultODataETagHandler().CreateETag(properties);

            ODataPath odataPath = new ODataPath(new EntitySetSegment(model.Customers));
            request.ODataProperties().Path = odataPath;

            // Act
            ETag<Customer> result = request.GetETag<Customer>(etagHeaderValue);
            dynamic dynamicResult = result;

            // Assert
            Assert.Equal("Foo", result["City"]);
            Assert.Equal("Foo", dynamicResult.City);
        }
示例#18
0
        private static bool HasControllerForEntitySetOrSingleton(ODataPath odataPath, HttpRequestMessage request)
        {
            string controllerName = null;

            var firstSegment = odataPath.Segments.FirstOrDefault();

            if (firstSegment != null)
            {
                if (firstSegment is EntitySetSegment entitySetSegment)
                {
                    controllerName = entitySetSegment.EntitySet.Name;
                }
                else
                {
                    if (firstSegment is SingletonSegment singletonSegment)
                    {
                        controllerName = singletonSegment.Singleton.Name;
                    }
                }
            }

            if (controllerName != null)
            {
                var services = request.GetConfiguration().Services;

                var controllers = services.GetHttpControllerSelector().GetControllerMapping();
                if (controllers.TryGetValue(controllerName, out var descriptor) && descriptor != null)
                {
                    // If there is a controller, check whether there is an action
                    if (HasSelectableAction(request, descriptor))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
示例#19
0
        /// <remarks>This signature uses types that are AspNet-specific.</remarks>
        public static Uri GenerateODataLink(HttpRequestMessage request, object entity, bool isEntityId)
        {
            IEdmModel model = request.GetModel();

            if (model == null)
            {
                throw new InvalidOperationException(SRResources.RequestMustHaveModel);
            }

            ODataPath path = request.ODataProperties().Path;

            if (path == null)
            {
                throw new InvalidOperationException(SRResources.ODataPathMissing);
            }

            IEdmNavigationSource navigationSource = path.NavigationSource;

            if (navigationSource == null)
            {
                throw new InvalidOperationException(SRResources.NavigationSourceMissingDuringSerialization);
            }

            ODataSerializerContext serializerContext = new ODataSerializerContext
            {
                NavigationSource = navigationSource,
                Model            = model,
                Url           = request.GetUrlHelper() ?? new UrlHelper(request),
                MetadataLevel = ODataMetadataLevel.FullMetadata, // Used internally to always calculate the links.
                Request       = request,
                Path          = path
            };

            IEdmEntityTypeReference entityType      = GetEntityType(model, entity);
            ResourceContext         resourceContext = new ResourceContext(serializerContext, entityType, entity);

            return(GenerateODataLink(resourceContext, isEntityId));
        }
示例#20
0
        private static ODataQueryOptions GetQueryOptions(string queryOption)
        {
            string uri = "Http://localhost/RoutingCustomers?" + queryOption;

            ODataUriResolver resolver = new ODataUriResolver
            {
                EnableCaseInsensitive = true
            };

            var configuration = RoutingConfigurationFactory.CreateWithRootContainer("OData", b => b.AddService(ServiceLifetime.Singleton, sp => resolver));
            var request       = RequestFactory.Create(HttpMethod.Get, uri, configuration, "OData");

            IEdmModel model = ODataRoutingModel.GetModel();

            IEdmEntitySet  entityset  = model.EntityContainer.FindEntitySet("RoutingCustomers");
            IEdmEntityType entityType =
                model.SchemaElements.OfType <IEdmEntityType>().Single(e => e.Name == "RoutingCustomer");

            ODataPath         path    = new ODataPath(new[] { new EntitySetSegment(entityset) });
            ODataQueryContext context = new ODataQueryContext(model, entityType, path);

            return(new ODataQueryOptions(context, request));
        }
示例#21
0
        /// <summary>
        /// Selects OData controller based on parsed OData URI
        /// </summary>
        /// <param name="odataPath">Parsed OData URI</param>
        /// <param name="request">Incoming HttpRequest</param>
        /// <returns>Prefix for controller name</returns>
        public string SelectController(ODataPath odataPath, HttpRequestMessage request)
        {
            Ensure.NotNull(odataPath, nameof(odataPath));
            Ensure.NotNull(request, nameof(request));

            if (IsMetadataPath(odataPath))
            {
                return(null);
            }

            // If user has defined something like PeopleController for the entity set People,
            // Then whether there is an action in that controller is checked
            // If controller has action for request, will be routed to that controller.
            // Cannot mark EntitySetRoutingConversion has higher priority as there will no way
            // to route to RESTier controller if there is EntitySet controller but no related action.
            if (HasControllerForEntitySetOrSingleton(odataPath, request))
            {
                // Fall back to routing conventions defined by OData Web API.
                return(null);
            }

            return(RestierControllerName);
        }
示例#22
0
        /// <inheritdoc/>
        protected override string SelectAction(string requestMethod, ODataPath odataPath, TestControllerContext controllerContext, IList <string> actionList)
        {
            if (odataPath.PathTemplate == "~/entityset/key/property" || odataPath.PathTemplate == "~/entityset/key/cast/property")
            {
                var segment     = odataPath.Segments.Last() as PropertySegment;
                var property    = segment.Property;
                var declareType = property.DeclaringType as IEdmEntityType;
                if (declareType != null)
                {
                    var key = odataPath.Segments[1] as KeySegment;
                    controllerContext.AddKeyValueToRouteData(key);
                    string prefix = ODataHelper.GetHttpPrefix(requestMethod);
                    if (string.IsNullOrEmpty(prefix))
                    {
                        return(null);
                    }
                    string action = prefix + property.Name + "From" + declareType.Name;
                    return(actionList.Contains(action) ? action : prefix + property.Name);
                }
            }

            return(null);
        }
示例#23
0
        private static ODataQueryOptions CreateQueryOptions(string queryString)
        {
            const string DocsEntitySetName = "Docs";

            var builder = new ODataConventionModelBuilder();

            builder.EntitySet <Doc>(DocsEntitySetName);
            var model = builder.GetEdmModel();

            var config = new HttpConfiguration();

            config.EnableDependencyInjection();
            config.MapODataServiceRoute("odata", null, model);

            var request = new HttpRequestMessage(HttpMethod.Get, $"http://localhost/{DocsEntitySetName}?{queryString}");

            request.SetConfiguration(config);

            var path    = new ODataRoutingPath(new EntitySetSegment(model.FindDeclaredEntitySet(DocsEntitySetName)));
            var context = new ODataQueryContext(model, typeof(Doc), path);

            return(new ODataQueryOptions(context, request));
        }
示例#24
0
        public ODataPath TryComputeCanonicalContainingPath(ODataPath path)
        {
            Contract.Assert(path != null);
            Contract.Assert(path.Segments.Count >= 2);

            _segments = path.Segments.ToList();

            RemoveAllTypeCasts();

            // New ODataPath will be extended later to include any final required key or cast.
            RemovePathSegmentsAfterTheLastNavigationProperty();

            RemoveRedundantContainingPathSegments();

            AddTypeCastsIfNecessary();

            // Also remove the last navigation property segment, since it is not part of the containing path segments.
            if (_segments.Count > 0)
            {
                _segments.RemoveAt(_segments.Count - 1);
            }

            return(new ODataPath(_segments));
        }
示例#25
0
        internal static bool CanReadType(
            Type type,
            IEdmModel model,
            ODataPath path,
            IEnumerable <ODataPayloadKind> payloadKinds,
            Func <IEdmTypeReference, ODataDeserializer> getEdmTypeDeserializer,
            Func <Type, ODataDeserializer> getODataPayloadDeserializer)
        {
            if (type == null)
            {
                throw Error.ArgumentNull("type");
            }

            IEdmTypeReference expectedPayloadType;
            ODataDeserializer deserializer = GetDeserializer(type, path, model,
                                                             getEdmTypeDeserializer, getODataPayloadDeserializer, out expectedPayloadType);

            if (deserializer != null)
            {
                return(payloadKinds.Contains(deserializer.ODataPayloadKind));
            }

            return(false);
        }
        public static ODataQueryOptions <T> GetODataQueryOptions <T>(string queryString, IServiceProvider serviceProvider, IRouteBuilder routeBuilder) where T : class
        {
            ODataConventionModelBuilder builder = new ODataConventionModelBuilder(serviceProvider);

            builder.EntitySet <T>(typeof(T).Name);
            IEdmModel     model     = builder.GetEdmModel();
            IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet(typeof(T).Name);

            Microsoft.AspNet.OData.Routing.ODataPath path = new Microsoft.AspNet.OData.Routing.ODataPath(new EntitySetSegment(entitySet));

            routeBuilder.EnableDependencyInjection();

            return(new ODataQueryOptions <T>
                   (
                       new ODataQueryContext(model, typeof(T), path),
                       BuildRequest
                       (
                           new DefaultHttpContext()
            {
                RequestServices = serviceProvider
            }.Request,
                           new Uri(BASEADDRESS + queryString)
                       )
                   ));
示例#27
0
        public async Task NullPrimitiveValueSerializeAsODataThrows(Type valueType, object value, string mediaType, string unused)
        {
            // Arrange
            Assert.NotNull(valueType);
            Assert.NotNull(unused);

            ODataConventionModelBuilder modelBuilder = ODataConventionModelBuilderFactory.Create();

            modelBuilder.EntitySet <WorkItem>("WorkItems");
            IEdmModel    model         = modelBuilder.GetEdmModel();
            IEdmProperty property      = model.EntityContainer.EntitySets().Single().EntityType().Properties().First();
            ODataPath    path          = new ODataPath(new PropertySegment(property as IEdmStructuralProperty));
            var          configuration = RoutingConfigurationFactory.CreateWithRootContainer("OData");
            var          request       = RequestFactory.Create(HttpMethod.Get, "http://localhost/WorkItems(10)/ID", configuration, "OData", path);

            var formatter = FormatterTestHelper.GetFormatter(new ODataPayloadKind[] { ODataPayloadKind.Property }, request, mediaType);

            // Act & Assert
            Type type    = (value != null) ? value.GetType() : typeof(Nullable <int>);
            var  content = FormatterTestHelper.GetContent(value, type, formatter, mediaType.ToString());
            await ExceptionAssert.ThrowsAsync <ODataException>(
                () => FormatterTestHelper.GetContentResult(content, request),
                "Cannot write the value 'null' in top level property; return 204 instead.");
        }
示例#28
0
        internal static void WriteToStream(
            Type type,
            object value,
            IEdmModel model,
            ODataVersion version,
            Uri baseAddress,
            MediaTypeHeaderValue contentType,
            IWebApiUrlHelper internaUrlHelper,
            IWebApiRequestMessage internalRequest,
            IWebApiHeaders internalRequestHeaders,
            Func <IServiceProvider, ODataMessageWrapper> getODataMessageWrapper,
            Func <IEdmTypeReference, ODataSerializer> getEdmTypeSerializer,
            Func <Type, ODataSerializer> getODataPayloadSerializer,
            Func <ODataSerializerContext> getODataSerializerContext)
        {
            if (model == null)
            {
                throw Error.InvalidOperation(SRResources.RequestMustHaveModel);
            }

            ODataSerializer serializer = GetSerializer(type, value, internalRequest, getEdmTypeSerializer, getODataPayloadSerializer);

            ODataPath            path = internalRequest.Context.Path;
            IEdmNavigationSource targetNavigationSource = path == null ? null : path.NavigationSource;

            // serialize a response
            string preferHeader     = RequestPreferenceHelpers.GetRequestPreferHeader(internalRequestHeaders);
            string annotationFilter = null;

            if (!String.IsNullOrEmpty(preferHeader))
            {
                ODataMessageWrapper messageWrapper = getODataMessageWrapper(null);
                messageWrapper.SetHeader(RequestPreferenceHelpers.PreferHeaderName, preferHeader);
                annotationFilter = messageWrapper.PreferHeader().AnnotationFilter;
            }

            IODataResponseMessage responseMessage = getODataMessageWrapper(internalRequest.RequestContainer);

            if (annotationFilter != null)
            {
                responseMessage.PreferenceAppliedHeader().AnnotationFilter = annotationFilter;
            }

            ODataMessageWriterSettings writerSettings = internalRequest.WriterSettings;

            writerSettings.BaseUri     = baseAddress;
            writerSettings.Version     = version;
            writerSettings.Validations = writerSettings.Validations & ~ValidationKinds.ThrowOnUndeclaredPropertyForNonOpenType;

            string metadataLink = internaUrlHelper.CreateODataLink(MetadataSegment.Instance);

            if (metadataLink == null)
            {
                throw new SerializationException(SRResources.UnableToDetermineMetadataUrl);
            }

            //Set this variable if the SelectExpandClause is different from the processed clause on the Query options
            SelectExpandClause selectExpandDifferentFromQueryOptions = null;

            if (internalRequest.Context.QueryOptions != null && internalRequest.Context.QueryOptions.SelectExpand != null)
            {
                if (internalRequest.Context.QueryOptions.SelectExpand.ProcessedSelectExpandClause != internalRequest.Context.ProcessedSelectExpandClause)
                {
                    selectExpandDifferentFromQueryOptions = internalRequest.Context.ProcessedSelectExpandClause;
                }
            }
            else if (internalRequest.Context.ProcessedSelectExpandClause != null)
            {
                selectExpandDifferentFromQueryOptions = internalRequest.Context.ProcessedSelectExpandClause;
            }

            writerSettings.ODataUri = new ODataUri
            {
                ServiceRoot = baseAddress,

                SelectAndExpand = internalRequest.Context.ProcessedSelectExpandClause,
                Apply           = internalRequest.Context.ApplyClause,
                Path            = ConvertPath(path),
            };

            ODataMetadataLevel metadataLevel = ODataMetadataLevel.MinimalMetadata;

            if (contentType != null)
            {
                IEnumerable <KeyValuePair <string, string> > parameters =
                    contentType.Parameters.Select(val => new KeyValuePair <string, string>(val.Name, val.Value));
                metadataLevel = ODataMediaTypes.GetMetadataLevel(contentType.MediaType, parameters);
            }

            using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, writerSettings, model))
            {
                ODataSerializerContext writeContext = getODataSerializerContext();
                writeContext.NavigationSource = targetNavigationSource;
                writeContext.Model            = model;
                writeContext.RootElementName  = GetRootElementName(path) ?? "root";
                writeContext.SkipExpensiveAvailabilityChecks = serializer.ODataPayloadKind == ODataPayloadKind.ResourceSet;
                writeContext.Path          = path;
                writeContext.MetadataLevel = metadataLevel;
                writeContext.QueryOptions  = internalRequest.Context.QueryOptions;

                //Set the SelectExpandClause on the context if it was explicitly specified.
                if (selectExpandDifferentFromQueryOptions != null)
                {
                    writeContext.SelectExpandClause = selectExpandDifferentFromQueryOptions;
                }

                serializer.WriteObject(value, type, messageWriter, writeContext);
            }
        }
 protected abstract string SelectAction(string requestMethod, ODataPath odataPath, TestControllerContext controllerContext, IList <string> actionMap);
示例#30
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="queryable"></param>
        /// <param name="path"></param>
        /// <param name="applyCount"></param>
        /// <returns></returns>
        private async Task <(IQueryable Queryable, ETag Etag)> ApplyQueryOptionsAsync(IQueryable queryable, ODataPath path, bool applyCount)
        {
            ETag etag = null;

            if (shouldWriteRawValue)
            {
                // Query options don't apply to $value.
                return(queryable, null);
            }

            var properties = Request.ODataProperties();
            var model      = await Api.GetModelAsync().ConfigureAwait(false);

            var queryContext = new ODataQueryContext(model, queryable.ElementType, path);
            var queryOptions = new ODataQueryOptions(queryContext, Request);

            // Get etag for query request
            if (queryOptions.IfMatch != null)
            {
                etag = queryOptions.IfMatch;
            }
            else if (queryOptions.IfNoneMatch != null)
            {
                etag = queryOptions.IfNoneMatch;
            }

            // TODO GitHubIssue#41 : Ensure stable ordering for query
            var settings = Api.GetApiService <ODataQuerySettings>();

            if (shouldReturnCount)
            {
                // Query options other than $filter and $search don't apply to $count.
                queryable = queryOptions.ApplyTo(queryable, settings, AllowedQueryOptions.All ^ AllowedQueryOptions.Filter);
                return(queryable, etag);
            }

            if (queryOptions.Count != null && !applyCount)
            {
                var queryExecutorOptions = Api.GetApiService <RestierQueryExecutorOptions>();
                queryExecutorOptions.IncludeTotalCount = queryOptions.Count.Value;
                queryExecutorOptions.SetTotalCount     = value => properties.TotalCount = value;
            }

            // Validate query before apply, and query setting like MaxExpansionDepth can be customized here
            var validationSettings = Api.GetApiService <ODataValidationSettings>();

            queryOptions.Validate(validationSettings);

            // Entity count can NOT be evaluated at this point of time because the source
            // expression is just a placeholder to be replaced by the expression sourcer.
            if (!applyCount)
            {
                queryable = queryOptions.ApplyTo(queryable, settings, AllowedQueryOptions.Count);
            }
            else
            {
                queryable = queryOptions.ApplyTo(queryable, settings);
            }

            return(queryable, etag);
        }