public void AddOData_RegistersODataOptionsWithServiceProvider()
        {
            // Arrange
            var services = new ServiceCollection();

            services.AddLogging();
            IEdmModel coreModel = EdmCoreModel.Instance;

            services.AddSingleton(_ => coreModel);

            // Act
            services.AddOData((options, serviceProvider) =>
            {
                var edmModel = serviceProvider.GetRequiredService <IEdmModel>();
                options.AddModel("odata", edmModel);
            });

            IServiceProvider provider = services.BuildServiceProvider();

            // Assert
            IOptions <ODataOptions> options = provider.GetService <IOptions <ODataOptions> >();

            Assert.NotNull(options);

            ODataOptions odataOptions = options.Value;
            var          model        = Assert.Single(odataOptions.Models);

            Assert.Equal("odata", model.Key);
            Assert.Same(coreModel, model.Value.Item1);
            Assert.NotNull(model.Value.Item2);
        }
示例#2
0
        public async Task <IQueryable> ApplyQuery(IQueryable collection)
        {
            T = collection.GetType().GetGenericArguments()[0];
            ODataOptions.Validate(ODataValidationSettings);

            return(await Task.Run(() => ODataOptions.ApplyTo(collection.AsQueryable())));
        }
示例#3
0
        public void Register(ODataOptions options)
        {
            ODataModelBuilder builder = new ODataConventionModelBuilder();

            builder.EntitySet <Person>("PersonApi");
            options.AddRouteComponents("odata", builder.GetEdmModel());
        }
示例#4
0
        private void Initialize(ODataOptions options)
        {
            Contract.Assert(options != null);

            foreach (var model in options.Models)
            {
                IServiceProvider subServiceProvider = model.Value.Item2;
                if (subServiceProvider == null)
                {
                    continue;
                }

                // If a batch handler is present, register the route with the batch path mapper. This will be used
                // by the batching middleware to handle the batch request. Batching still requires the injection
                // of the batching middleware via UseODataBatching().
                ODataBatchHandler batchHandler = subServiceProvider.GetService <ODataBatchHandler>();
                if (batchHandler != null)
                {
                    batchHandler.PrefixName = model.Key;
                    string batchPath = string.IsNullOrEmpty(model.Key)  ? "/$batch" : $"/{model.Key}/$batch";

                    if (_batchMapping == null)
                    {
                        _batchMapping = new ODataBatchPathMapping();
                    }

                    _batchMapping.AddRoute(model.Key, batchPath, batchHandler);
                }
            }
        }
        public void OnProvidersExecuted_AddODataRoutingSelector_WhenAttributeRoutingConvention()
        {
            // Arrange
            ODataOptions options = new ODataOptions();

            options.AddModel("odata", _model);

            LoggerFactory            loggerFactory = new LoggerFactory();
            var                      logger        = new Logger <AttributeRoutingConvention>(loggerFactory);
            IODataPathTemplateParser parser        = new DefaultODataPathTemplateParser();

            IODataControllerActionConvention[] conventions = new IODataControllerActionConvention[]
            {
                new AttributeRoutingConvention(logger, parser)
            };

            ODataRoutingApplicationModelProvider provider        = CreateProvider(options, conventions);
            ApplicationModelProviderContext      providerContext = CreateProviderContext(typeof(AttributeRoutingController));

            // Act
            provider.OnProvidersExecuted(providerContext);

            // Assert
            ControllerModel controller = Assert.Single(providerContext.Result.Controllers);

            ActionModel action = Assert.Single(controller.Actions);

            Assert.Equal("AnyMethodNameHere", action.ActionMethod.Name);
            Assert.Single(action.Parameters);
            Assert.Equal(2, action.Selectors.Count);
            Assert.Equal(new[] { "odata/Customers({key})/Name", "odata/Customers/{key}/Name" }, action.Selectors.Select(s => s.AttributeRouteModel.Template));
        }
示例#6
0
        /// <inheritdoc/>
        public override async Task ProcessBatchAsync(HttpContext context, RequestDelegate nextHandler)
        {
            if (context == null)
            {
                throw Error.ArgumentNull("context");
            }
            if (nextHandler == null)
            {
                throw Error.ArgumentNull("nextHandler");
            }

            if (!await ValidateRequest(context.Request))
            {
                return;
            }

            IList <ODataBatchRequestItem> subRequests = await ParseBatchRequestsAsync(context);

            ODataOptions options = context.RequestServices.GetRequiredService <ODataOptions>();
            bool         enableContinueOnErrorHeader = (options != null)
                ? options.EnableContinueOnErrorHeader
                : false;

            SetContinueOnError(new WebApiRequestHeaders(context.Request.Headers), enableContinueOnErrorHeader);

            IList <ODataBatchResponseItem> responses = await ExecuteRequestMessagesAsync(subRequests, nextHandler);

            await CreateResponseMessageAsync(responses, context.Request);
        }
示例#7
0
        /// <summary>
        /// Initializes a new instance of the WebApiRequestMessage class.
        /// </summary>
        /// <param name="request">The inner request.</param>
        public WebApiRequestMessage(HttpRequest request)
        {
            if (request == null)
            {
                throw Error.ArgumentNull("request");
            }

            this.innerRequest = request;
            this.Headers      = new WebApiRequestHeaders(request.Headers);

            IODataFeature feature = request.ODataFeature();

            if (feature != null)
            {
                this.Context = new WebApiContext(feature);
            }

            // Get the ODataOptions from the global service provider.
            ODataOptions options = request.HttpContext.RequestServices.GetRequiredService <ODataOptions>();

            if (options != null)
            {
                this.Options = new WebApiOptions(options);
            }
        }
示例#8
0
        public static ODataQueryOptions <T> GetODataQueryOptions <T>(string queryString, IServiceProvider serviceProvider) where T : class
        {
            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();

            builder.EntitySet <T>(typeof(T).Name);
            IEdmModel     model     = builder.GetEdmModel();
            IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet(typeof(T).Name);
            ODataPath     path      = new ODataPath(new Microsoft.OData.UriParser.EntitySetSegment(entitySet));

            var request = new DefaultHttpContext()
            {
                RequestServices = serviceProvider
            }.Request;

            var oDataOptions = new ODataOptions().AddRouteComponents("key", model,
                                                                     x => x.AddSingleton <ISearchBinder, OpsTenantSearchBinder>());

            var(_, routeProvider) = oDataOptions.RouteComponents["key"];

            request.ODataFeature().Services = routeProvider;
            var oDataQueryOptions           = new ODataQueryOptions <T>
                                              (
                new ODataQueryContext(model, typeof(T), path),
                BuildRequest(request, new Uri(BASEADDRESS + queryString))
                                              );

            return(oDataQueryOptions);
        private static ODataRoutingApplicationModelProvider CreateProvider(ODataOptions options,
                                                                           IEnumerable <IODataControllerActionConvention> conventions)
        {
            IOptions <ODataOptions> odataOptions = Options.Create(options);

            return(new ODataRoutingApplicationModelProvider(conventions, odataOptions));
        }
        /// <inheritdoc/>
        public override async Task ProcessBatchAsync(HttpContext context, RequestDelegate nextHandler)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (nextHandler == null)
            {
                throw new ArgumentNullException(nameof(nextHandler));
            }

            if (!await ValidateRequest(context.Request).ConfigureAwait(false))
            {
                return;
            }

            IList <ODataBatchRequestItem> subRequests = await ParseBatchRequestsAsync(context).ConfigureAwait(false);

            // ODataOptions options = context.RequestServices.GetRequiredService<ODataOptions>();
            ODataOptions options = context.RequestServices.GetRequiredService <IOptions <ODataOptions> >().Value;
            bool         enableContinueOnErrorHeader = (options != null)
                ? options.EnableContinueOnErrorHeader
                : false;

            SetContinueOnError(context.Request.Headers, enableContinueOnErrorHeader);

            IList <ODataBatchResponseItem> responses = await ExecuteRequestMessagesAsync(subRequests, nextHandler).ConfigureAwait(false);

            await CreateResponseMessageAsync(responses, context.Request).ConfigureAwait(false);
        }
示例#11
0
 public IActionResult Index(ODataOptions <Entity> options)
 {
     return(View(new ODataSqlQuery(
                     "SELECT FROM Entities WHERE OwnerId = @p0",
                     10456, options
                     )));
 }
        /// <summary>
        /// Gets the dependency injection container for the OData request.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>The dependency injection container.</returns>
        public static IServiceProvider GetSubServiceProvider(this HttpRequest request)
        {
            if (request == null)
            {
                throw Error.ArgumentNull(nameof(request));
            }

            IServiceProvider requestContainer = request.ODataFeature().SubServiceProvider;

            if (requestContainer != null)
            {
                return(requestContainer);
            }

            IOptions <ODataOptions> odataOptionsOptions = request.HttpContext.RequestServices.GetRequiredService <IOptions <ODataOptions> >();

            if (odataOptionsOptions == null)
            {
                throw Error.InvalidOperation(SRResources.MissingODataServices, nameof(ODataOptions));
            }

            ODataOptions options = odataOptionsOptions.Value;

            return(options.GetODataServiceProvider(request.ODataFeature().PrefixName));

            // HTTP routes will not have chance to call CreateRequestContainer. We have to call it.
            // return request.CreateSubServiceProvider(request.ODataFeature().PrefixName);
        }
 static AttributeRoutingConventionTests()
 {
     _edmModel = GetEdmModel();
     _options  = new ODataOptions();
     _options.AddModel(_edmModel);
     _attributeConvention = CreateConvention();
 }
示例#14
0
        public void AddODataWithSetup_OnMvcCoreBuilder_RegistersODataOptions()
        {
            // Arrange
            var services = new ServiceCollection();

            services.AddLogging();
            IMvcCoreBuilder builder = new MyMvcCoreBuilder
            {
                Services = services
            };

            IEdmModel coreModel = EdmCoreModel.Instance;

            // Act
            builder.AddOData(opt => opt.AddModel("odata", EdmCoreModel.Instance));
            IServiceProvider provider = services.BuildServiceProvider();

            // Assert
            IOptions <ODataOptions> options = provider.GetService <IOptions <ODataOptions> >();

            Assert.NotNull(options);

            ODataOptions odataOptions = options.Value;
            var          model        = Assert.Single(odataOptions.Models);

            Assert.Equal("odata", model.Key);
            Assert.Same(coreModel, model.Value.Item1);
            Assert.NotNull(model.Value.Item2);
        }
        public void SetDefaultODataOptions()
        {
            var defaultOptions = new ODataOptions
            {
                NullDynamicPropertyIsEnabled = false,
                EnableContinueOnErrorHeader  = false,
                CompatibilityOptions         = CompatibilityOptions.AllowNextLinkWithNonPositiveTopValue,
                UrlKeyDelimiter = ODataUrlKeyDelimiter.Slash
            };
            var services = new ServiceCollection();

            services.Insert(0, ServiceDescriptor.Singleton(new ODataOptions
            {
                NullDynamicPropertyIsEnabled = true,
                EnableContinueOnErrorHeader  = true,
                CompatibilityOptions         = CompatibilityOptions.None,
                UrlKeyDelimiter = ODataUrlKeyDelimiter.Parentheses
            }));
            ODataOptions updatedOptions;

            using (var serviceProvider = services.BuildServiceProvider())
            {
                serviceProvider.SetDefaultODataOptions(defaultOptions);
                updatedOptions = serviceProvider.GetRequiredService <ODataOptions>();
            }

            Assert.Equal(defaultOptions.NullDynamicPropertyIsEnabled, updatedOptions.NullDynamicPropertyIsEnabled);
            Assert.Equal(defaultOptions.EnableContinueOnErrorHeader, updatedOptions.EnableContinueOnErrorHeader);
            Assert.Equal(defaultOptions.CompatibilityOptions, updatedOptions.CompatibilityOptions);
            Assert.Equal(defaultOptions.UrlKeyDelimiter, updatedOptions.UrlKeyDelimiter);
        }
示例#16
0
        public void PropertySetting_SetsCorrectValue()
        {
            // Arrange
            ODataOptions options = new ODataOptions();

            // verify default
            Assert.Equal(ODataUrlKeyDelimiter.Slash, options.UrlKeyDelimiter); // Guard
            Assert.False(options.EnableContinueOnErrorHeader);
            Assert.True(options.EnableAttributeRouting);
            Assert.Null(options.BuilderFactory);
            Assert.Equal(TimeZoneInfo.Local, options.TimeZone);
            Assert.True(options.RouteOptions.EnableKeyAsSegment);
            Assert.True(options.EnableNoDollarQueryOptions);

            // Act
            options.UrlKeyDelimiter             = ODataUrlKeyDelimiter.Parentheses;
            options.EnableContinueOnErrorHeader = true;
            options.EnableAttributeRouting      = false;
            options.BuilderFactory = () => null;
            options.TimeZone       = TimeZoneInfo.Utc;
            options.RouteOptions.EnableKeyAsSegment = false;
            options.EnableNoDollarQueryOptions      = false;

            // Act & Assert
            Assert.Equal(ODataUrlKeyDelimiter.Parentheses, options.UrlKeyDelimiter);
            Assert.True(options.EnableContinueOnErrorHeader);
            Assert.False(options.EnableAttributeRouting);
            Assert.NotNull(options.BuilderFactory);
            Assert.Equal(TimeZoneInfo.Utc, options.TimeZone);
            Assert.False(options.RouteOptions.EnableKeyAsSegment);
            Assert.False(options.EnableNoDollarQueryOptions);

            Assert.Empty(options.Models);
        }
示例#17
0
        /// <inheritdoc/>
        public override async Task ProcessBatchAsync(HttpContext context, RequestDelegate nextHandler)
        {
            if (context == null)
            {
                throw Error.ArgumentNull("context");
            }
            if (nextHandler == null)
            {
                throw Error.ArgumentNull("nextHandler");
            }

            if (!await ValidateRequest(context.Request))
            {
                return;
            }

            // This container is for the overall batch request.
            HttpRequest      request          = context.Request;
            IServiceProvider requestContainer = request.CreateRequestContainer(ODataRouteName);

            requestContainer.GetRequiredService <ODataMessageReaderSettings>().BaseUri = GetBaseUri(request);

            ODataMessageReader reader = request.GetODataMessageReader(requestContainer);

            ODataBatchReader batchReader = await reader.CreateODataBatchReaderAsync();

            List <ODataBatchResponseItem> responses = new List <ODataBatchResponseItem>();
            Guid batchId = Guid.NewGuid();

            ODataOptions options = context.RequestServices.GetRequiredService <ODataOptions>();
            bool         enableContinueOnErrorHeader = (options != null)
                ? options.EnableContinueOnErrorHeader
                : false;

            SetContinueOnError(new WebApiRequestHeaders(request.Headers), enableContinueOnErrorHeader);

            while (await batchReader.ReadAsync())
            {
                ODataBatchResponseItem responseItem = null;
                if (batchReader.State == ODataBatchReaderState.ChangesetStart)
                {
                    responseItem = await ExecuteChangeSetAsync(batchReader, batchId, request, nextHandler);
                }
                else if (batchReader.State == ODataBatchReaderState.Operation)
                {
                    responseItem = await ExecuteOperationAsync(batchReader, batchId, request, nextHandler);
                }
                if (responseItem != null)
                {
                    responses.Add(responseItem);
                    if (responseItem.IsResponseSuccessful() == false && ContinueOnError == false)
                    {
                        break;
                    }
                }
            }

            await CreateResponseMessageAsync(responses, request);
        }
示例#18
0
 public MyODataRoutingMatcherPolicy(IODataTemplateTranslator translator,
                                    IODataModelProvider provider,
                                    IOptions <ODataOptions> options)
 {
     _translator = translator;
     _provider   = provider;
     _options    = options.Value;
 }
示例#19
0
        public void AddRouteComponents_Throws_IfRoutePrefixNull()
        {
            // Arrange
            ODataOptions options = new ODataOptions();

            // Act & Assert
            ExceptionAssert.ThrowsArgumentNull(() => options.AddRouteComponents(null, EdmCoreModel.Instance, builder => { }), "routePrefix");
        }
示例#20
0
        public void GetRouteServices_ReturnsNull()
        {
            // Arrange
            ODataOptions options = new ODataOptions();

            // Act & Assert
            Assert.Null(options.GetRouteServices(null));
        }
示例#21
0
        public void AddModel_Throws_IfModelNull()
        {
            // Arrange
            ODataOptions options = new ODataOptions();

            // Act & Assert
            ExceptionAssert.ThrowsArgumentNull(() => options.AddModel("odata", null, builder => { }), "model");
        }
示例#22
0
        public DynamicsSignInManager(UserManager <TUser> userManager, IHttpContextAccessor contextAccessor, IUserClaimsPrincipalFactory <TUser> claimsFactory, IOptions <IdentityOptions> optionsAccessor, ILogger <SignInManager <TUser> > logger, IOptions <ODataOptions> odataOptions)
            : base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger)
        {
            var context = contextAccessor.HttpContext;

            this.authenticationManager = context.Authentication;
            this.odataOptions          = odataOptions.Value;
        }
示例#23
0
        public void ODataOptionsSetup_DoesNotSetup_ODataRoutingConventions()
        {
            // Arrange & Act
            ODataOptions options = GetODataOptions(false);

            // Assert
            Assert.Empty(options.Conventions);
        }
示例#24
0
        public void GetODataServiceProvider_ReturnsNull()
        {
            // Arrange
            ODataOptions options = new ODataOptions();

            // Act & Assert
            Assert.Null(options.GetODataServiceProvider(null));
        }
        static void ConfigurePathHandler(this IServiceProvider rootContainer, ODataOptions options)
        {
            var pathHandler = rootContainer.GetRequiredService <IODataPathHandler>();

            if (pathHandler != null && pathHandler.UrlKeyDelimiter == null)
            {
                pathHandler.UrlKeyDelimiter = options.UrlKeyDelimiter;
            }
        }
        public ODataService(IPrincipal user, IDynamicsHttpClient httpClient, IOptions <ODataOptions> odataOptions, ILockEntityService lockEntityService)
        {
            this.user              = user as ClaimsPrincipal;
            this.odataOptions      = odataOptions.Value;
            this.httpClient        = httpClient;
            this.lockEntityService = lockEntityService;

            BuildUrls();
        }
        public void SetMaxTop_Throws_ForWrongValue()
        {
            // Arrange
            ODataOptions options = new ODataOptions();

            // Act & Assert
            ArgumentOutOfRangeException exception = ExceptionAssert.Throws <ArgumentOutOfRangeException>(() => options.SetMaxTop(-2));

            Assert.Contains("Value must be greater than or equal to 0", exception.Message);
        }
        /// <summary>
        /// Initialize the middleware
        /// </summary>
        /// <param name="options">The OData options.</param>
        private void Initialize(ODataOptions options)
        {
            Contract.Assert(options != null);

            foreach (var model in options.Models)
            {
                string openapiPath = string.IsNullOrEmpty(model.Key) ? $"/{_requestName}" : $"/{model.Key}/{_requestName}";
                AddRoute(model.Key, openapiPath);
            }
        }
示例#29
0
        /// <summary>
        /// Initializes a new instance of the WebApiOptions class.
        /// </summary>
        /// <param name="options">The inner options.</param>
        public WebApiOptions(ODataOptions options)
        {
            if (options == null)
            {
                throw Error.ArgumentNull("options");
            }

            this.NullDynamicPropertyIsEnabled = options.NullDynamicPropertyIsEnabled;
            this.UrlKeyDelimiter = options.UrlKeyDelimiter;
        }
        /// <summary>
        /// Get the UrlKeyDelimiter in DefaultODataPathHandler.
        /// </summary>
        /// <param name="builder">The <see cref="IEndpointRouteBuilder"/>.</param>
        internal static ODataUrlKeyDelimiter GetUrlKeyDelimiter(this IEndpointRouteBuilder builder)
        {
            if (builder == null)
            {
                throw Error.ArgumentNull("builder");
            }

            ODataOptions defaultOptions = builder.GetDefaultODataOptions();

            return(defaultOptions.UrlKeyDelimiter);
        }