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); }
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); }
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); }
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); }
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); }
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); }
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); } }
// 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); }
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); }
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); }
/// <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)); }
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)); }
/// <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); }
/// <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); }
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)); }
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)); }
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) ) ));
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."); }
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);
/// <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); }