public static SwaggerRouteBuilder AddCustomSwaggerRoute(this HttpConfiguration httpConfig, ODataRoute oDataRoute, string routeTemplate) { Contract.Requires(httpConfig != null); Contract.Requires(oDataRoute != null); Contract.Requires(httpConfig.Properties != null); Contract.Ensures(Contract.Result<SwaggerRouteBuilder>() != null); oDataRoute.SetHttpConfiguration(httpConfig); var urlDecodedTemplate = HttpUtility.UrlDecode(routeTemplate); Contract.Assume(!string.IsNullOrWhiteSpace(urlDecodedTemplate)); var swaggerRoute = new SwaggerRoute(urlDecodedTemplate, oDataRoute); var swaggerRouteBuilder = new SwaggerRouteBuilder(swaggerRoute); httpConfig.Properties.AddOrUpdate(oDataRoute, key => new List<SwaggerRoute> { swaggerRoute }, (key, value) => { var swaggerRoutes = value as List<SwaggerRoute>; swaggerRoutes.Add(swaggerRoute); return swaggerRoutes; }); return swaggerRouteBuilder; }
public void GenerateLinkDirectly_ReturnsNull_IfHelperRequestHasNoConfiguration() { HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/vpath/prefix/Customers"); ODataRoute odataRoute = new ODataRoute("prefix", pathConstraint: null); Assert.Null(odataRoute.GenerateLinkDirectly(request, "odataPath")); }
private static HttpRequestMessage CreateHttpRequestMessage(HttpActionDescriptor actionDescriptor, ODataRoute oDataRoute, HttpConfiguration httpConfig) { Contract.Requires(httpConfig != null); Contract.Requires(oDataRoute != null); Contract.Requires(httpConfig != null); Contract.Ensures(Contract.Result<HttpRequestMessage>() != null); Contract.Assume(oDataRoute.Constraints != null); var httpRequestMessage = new HttpRequestMessage(actionDescriptor.SupportedHttpMethods.First(), "http://any/"); var requestContext = new HttpRequestContext { Configuration = httpConfig }; httpRequestMessage.SetConfiguration(httpConfig); httpRequestMessage.SetRequestContext(requestContext); var httpRequestMessageProperties = httpRequestMessage.ODataProperties(); Contract.Assume(httpRequestMessageProperties != null); httpRequestMessageProperties.Model = oDataRoute.GetEdmModel(); httpRequestMessageProperties.RouteName = oDataRoute.GetODataPathRouteConstraint().RouteName; httpRequestMessageProperties.RoutingConventions = oDataRoute.GetODataPathRouteConstraint().RoutingConventions; httpRequestMessageProperties.PathHandler = oDataRoute.GetODataPathRouteConstraint().PathHandler; return httpRequestMessage; }
public void CanGenerateDirectLink_IsFalse_IfRouteTemplateHasParameterInPrefix() { // Arrange && Act ODataRoute odataRoute = new ODataRoute("{prefix}", pathConstraint: null); // Assert Assert.False(odataRoute.CanGenerateDirectLink); }
public void GenerateLinkDirectly_ReturnsNull_IfRouteTemplateHasParameterInPrefix() { HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/vpath/prefix/Customers"); HttpConfiguration config = new HttpConfiguration(new HttpRouteCollection("http://localhost/vpath")); request.SetConfiguration(config); ODataRoute odataRoute = new ODataRoute("{prefix}", pathConstraint: null); Assert.Null(odataRoute.GenerateLinkDirectly(request, "odataPath")); }
private static IEnumerable<SwaggerRoute> GenerateOperationImportRoutes(ODataRoute oDataRoute) { Contract.Requires(oDataRoute != null); Contract.Requires(oDataRoute.Constraints != null); return oDataRoute.GetEdmModel() .EntityContainer .OperationImports()? .Select(operationImport => new SwaggerRoute(ODataSwaggerUtilities.GetPathForOperationImport(operationImport), oDataRoute, ODataSwaggerUtilities.CreateSwaggerPathForOperationImport(operationImport, oDataRoute))); }
public SwaggerRoute(string template, ODataRoute oDataRoute, PathItem pathItem) { Contract.Requires(!string.IsNullOrWhiteSpace(template)); Contract.Requires(pathItem != null); Contract.Requires(oDataRoute != null); _template = template; _oDataRoute = oDataRoute; _pathItem = pathItem; }
private static ODataActionDescriptor GetODataActionDescriptorFromAttributeRoute(HttpActionDescriptor actionDescriptor, ODataRoute oDataRoute, HttpConfiguration httpConfig) { Contract.Requires(actionDescriptor != null); Contract.Requires(oDataRoute != null); Contract.Ensures(Contract.Result<ODataActionDescriptor>() != null); var odataRouteAttribute = actionDescriptor.GetCustomAttributes<ODataRouteAttribute>()?.FirstOrDefault(); Contract.Assume(odataRouteAttribute != null); var pathTemplate = HttpUtility.UrlDecode(oDataRoute.GetRoutePrefix().AppendPathSegment(odataRouteAttribute.PathTemplate)); Contract.Assume(pathTemplate != null); return new ODataActionDescriptor(actionDescriptor, oDataRoute, pathTemplate, CreateHttpRequestMessage(actionDescriptor, oDataRoute, httpConfig)); }
public static List<SwaggerRoute> GetCustomSwaggerRoutes(HttpConfiguration httpConfig, ODataRoute oDataRoute) { Contract.Requires(httpConfig != null); Contract.Requires(oDataRoute != null); Contract.Requires(httpConfig.Properties != null); Contract.Ensures(Contract.Result<List<SwaggerRoute>>() != null); object swaggerRoutes; httpConfig.Properties.TryGetValue(oDataRoute, out swaggerRoutes); return swaggerRoutes as List<SwaggerRoute> ?? new List<SwaggerRoute>(); }
/// <summary> /// Initialize the operations to Swagger model. /// </summary> /// <param name="oDataRoute">The o data route.</param> /// <returns></returns> private static IEnumerable<SwaggerRoute> GenerateOperationRoutes(ODataRoute oDataRoute) { Contract.Requires(oDataRoute != null); Contract.Requires(oDataRoute.Constraints != null); var routes = new List<SwaggerRoute>(); var edmSchemaElements = oDataRoute.GetEdmModel().SchemaElements; if (edmSchemaElements != null) { foreach (var operation in edmSchemaElements.OfType<IEdmOperation>()) { // skip unbound operation if (!operation.IsBound) { continue; } var edmOperationParameters = operation.Parameters; if (edmOperationParameters != null && edmOperationParameters.Any()) { var boundParameter = edmOperationParameters.First(); Contract.Assume(boundParameter != null); var boundType = boundParameter.GetOperationType().GetDefinition(); // skip operation bound to non entity (or entity collection) if (boundType.TypeKind == EdmTypeKind.Entity) { var entityType = (IEdmEntityType)boundType; var edmEntitySets = oDataRoute.GetEdmModel().EntityContainer.EntitySets(); Contract.Assume(edmEntitySets != null); routes.AddRange(edmEntitySets.Where(es => es.GetEntityType().Equals(entityType)).Select(entitySet => new SwaggerRoute(ODataSwaggerUtilities.GetPathForOperationOfEntity(operation, entitySet), oDataRoute, ODataSwaggerUtilities.CreateSwaggerPathForOperationOfEntity(operation, entitySet)))); } else if (boundType.TypeKind == EdmTypeKind.Collection) { var collectionType = boundType as IEdmCollectionType; if (collectionType?.ElementType?.GetDefinition().TypeKind == EdmTypeKind.Entity) { var entityType = (IEdmEntityType)collectionType.ElementType?.GetDefinition(); var edmEntitySets = oDataRoute.GetEdmModel().EntityContainer.EntitySets(); Contract.Assume(edmEntitySets != null); routes.AddRange(edmEntitySets.Where(es => es.GetEntityType().Equals(entityType)).Select(entitySet => new SwaggerRoute(ODataSwaggerUtilities.GetPathForOperationOfEntitySet(operation, entitySet), oDataRoute, ODataSwaggerUtilities.CreateSwaggerPathForOperationOfEntitySet(operation, entitySet, oDataRoute)))); } } } } } return routes; }
public void GenerateLinkDirectly_DoesNotReturnNull_IfHelperRequestHasNoConfiguration() { // Arrange ODataRoute odataRoute = new ODataRoute("prefix", pathConstraint: null); // Act var virtualPathData = odataRoute.GenerateLinkDirectly("odataPath"); // Assert Assert.True(odataRoute.CanGenerateDirectLink); Assert.NotNull(virtualPathData); Assert.Equal("prefix/odataPath", virtualPathData.VirtualPath); }
public void GenerateLinkDirectly_DoesNotReturnNull_IfRoutePrefixIsNull() { // Arrange ODataRoute odataRoute = new ODataRoute(routePrefix: null, pathConstraint: null); // Act var virtualPathData = odataRoute.GenerateLinkDirectly("odataPath"); // Assert Assert.True(odataRoute.CanGenerateDirectLink); Assert.NotNull(virtualPathData); Assert.Equal("odataPath", virtualPathData.VirtualPath); }
/// <summary> /// Initializes a new instance of the <see cref="ODataActionDescriptor" /> class. /// </summary> /// <param name="actionDescriptor">The HTTP action descriptor.</param> /// <param name="route">The OData route.</param> /// <param name="relativePathTemplate">The relative path template.</param> /// <param name="request">The request.</param> /// <param name="operation">Additional metadata based about the action.</param> public ODataActionDescriptor(HttpActionDescriptor actionDescriptor, ODataRoute route, string relativePathTemplate, HttpRequestMessage request, Operation operation = null) { Contract.Requires(actionDescriptor != null); Contract.Requires(route != null); Contract.Requires(relativePathTemplate != null); Contract.Requires(request != null); ActionDescriptor = actionDescriptor; Route = route; RelativePathTemplate = relativePathTemplate; Request = request; Operation = operation; }
private static List<SwaggerRoute> Generate(ODataRoute oDataRoute) { Contract.Requires(oDataRoute != null); Contract.Requires(oDataRoute.Constraints != null); var routes = new List<SwaggerRoute>(); routes.AddRangeIfNotNull(GenerateEntitySetRoutes(oDataRoute)); routes.AddRangeIfNotNull(GenerateEntityRoutes(oDataRoute)); routes.AddRangeIfNotNull(GenerateOperationImportRoutes(oDataRoute)); routes.AddRangeIfNotNull(GenerateOperationRoutes(oDataRoute)); return routes; }
public void GetVirtualPath_MatchesHttpRoute(string odataPath) { HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/vpath/prefix/Customers"); HttpConfiguration config = new HttpConfiguration(new HttpRouteCollection("http://localhost/vpath")); request.SetConfiguration(config); IHttpRoute httpRoute = config.Routes.CreateRoute("prefix/{*odataPath}", defaults: null, constraints: null); ODataRoute odataRoute = new ODataRoute("prefix", pathConstraint: null); // Test that the link generated by ODataRoute matches the one generated by HttpRoute Assert.Equal( httpRoute.GetVirtualPath(request, new HttpRouteValueDictionary { { "odataPath", odataPath }, { "httproute", true } }).VirtualPath, odataRoute.GetVirtualPath(request, new HttpRouteValueDictionary { { "odataPath", odataPath }, { "httproute", true } }).VirtualPath); }
private static IEnumerable<ODataActionDescriptor> GetODataActionDescriptorsFromAttributeRoutes(ODataRoute oDataRoute, HttpConfiguration httpConfig) { Contract.Requires(oDataRoute != null); Contract.Requires(oDataRoute.Constraints != null); var rootContainer = httpConfig.GetODataRootContainer(oDataRoute); var routingConventions = rootContainer.GetServices<IODataRoutingConvention>(); var attributeRoutingConvention = routingConventions.OfType<AttributeRoutingConvention>().SingleOrDefault(); if (attributeRoutingConvention != null) { return attributeRoutingConvention .GetInstanceField<IDictionary<ODataPathTemplate, HttpActionDescriptor>>("_attributeMappings", true) .Select(pair => GetODataActionDescriptorFromAttributeRoute(pair.Value, oDataRoute, httpConfig)) .Where(descriptor => descriptor != null); } return new List<ODataActionDescriptor>(); }
public void GetVirtualPath_CanGenerateDirectLinkIsTrue_IfRoutePrefixIsNull() { // Arrange HttpRequestMessage request = new HttpRequestMessage( HttpMethod.Get, "http://localhost/vpath/prefix/Customers"); HttpConfiguration config = new HttpConfiguration(new HttpRouteCollection("http://localhost/vpath")); request.SetConfiguration(config); ODataRoute odataRoute = new ODataRoute(routePrefix: null, pathConstraint: null); // Act var virtualPathData = odataRoute.GetVirtualPath( request, new HttpRouteValueDictionary { { "odataPath", "odataPath" }, { "httproute", true } }); // Assert Assert.True(odataRoute.CanGenerateDirectLink); Assert.NotNull(virtualPathData); Assert.Equal("odataPath", virtualPathData.VirtualPath); }
private static IEnumerable<ODataActionDescriptor> GetODataActionDescriptorsFromAttributeRoutes(ODataRoute oDataRoute, HttpConfiguration httpConfig) { Contract.Requires(oDataRoute != null); Contract.Requires(oDataRoute.Constraints != null); var attributeRoutingConvention = (AttributeRoutingConvention)oDataRoute .GetODataPathRouteConstraint() .RoutingConventions? .SingleOrDefault(convention => convention is AttributeRoutingConvention); if (attributeRoutingConvention != null) { return attributeRoutingConvention .GetInstanceField<IDictionary<ODataPathTemplate, HttpActionDescriptor>>("_attributeMappings", true) .Select(pair => GetODataActionDescriptorFromAttributeRoute(pair.Value, oDataRoute, httpConfig)) .Where(descriptor => descriptor != null); } return new List<ODataActionDescriptor>(); }
/// <summary> /// Maps the specified OData route. When the <paramref name="defaultHandler"/> is non-<c>null</c>, it will map /// it as the handler for the route. /// </summary> /// <param name="configuration">The server configuration.</param> /// <param name="routeName">The name of the route to map.</param> /// <param name="routePrefix">The prefix to add to the OData route's path template.</param> /// <param name="model">The EDM model to use for parsing OData paths.</param> /// <param name="pathHandler">The <see cref="IODataPathHandler" /> to use for parsing the OData path.</param> /// <param name="routingConventions"> /// The OData routing conventions to use for controller and action selection. /// </param> /// <param name="defaultHandler">The default <see cref="HttpMessageHandler"/> for this route.</param> /// <returns>The added <see cref="ODataRoute"/>.</returns> public static ODataRoute MapODataServiceRoute(this HttpConfiguration configuration, string routeName, string routePrefix, IEdmModel model, IODataPathHandler pathHandler, IEnumerable<IODataRoutingConvention> routingConventions, HttpMessageHandler defaultHandler) { if (configuration == null) { throw Error.ArgumentNull("configuration"); } // We have a more specific overload to map batch handlers that creates a different route for the batch // endpoint instead of mapping that handler as the per route handler. Given that HttpMessageHandler is a // base type of ODataBatchHandler, it's possible the compiler will call this overload instead of the one // for the batch handler, so we detect that case and call the appropiate overload for the user. // The case in which the compiler picks the wrong overload is: // HttpRequestMessageHandler batchHandler = new DefaultODataBatchHandler(httpServer); // config.Routes.MapODataServiceRoute("routeName", "routePrefix", model, batchHandler); if (defaultHandler != null) { ODataBatchHandler batchHandler = defaultHandler as ODataBatchHandler; if (batchHandler != null) { return MapODataServiceRoute(configuration, routeName, routePrefix, model, batchHandler); } } HttpRouteCollection routes = configuration.Routes; routePrefix = RemoveTrailingSlash(routePrefix); DefaultODataPathHandler odataPathHandler = pathHandler as DefaultODataPathHandler; if (odataPathHandler != null) { odataPathHandler.ResolverSetttings = configuration.GetResolverSettings(); } ODataPathRouteConstraint routeConstraint = new ODataPathRouteConstraint(pathHandler, model, routeName, routingConventions); ODataRoute route = new ODataRoute( routePrefix, routeConstraint, defaults: null, constraints: null, dataTokens: null, handler: defaultHandler); routes.Add(routeName, route); return route; }
public static ODataRoute MapODataServiceRoute(this HttpConfiguration configuration, string routeName, string routePrefix, IEdmModel model, IODataPathHandler pathHandler, IEnumerable<IODataRoutingConvention> routingConventions, ODataBatchHandler batchHandler) { if (configuration == null) { throw Error.ArgumentNull("configuration"); } HttpRouteCollection routes = configuration.Routes; routePrefix = RemoveTrailingSlash(routePrefix); if (batchHandler != null) { batchHandler.ODataRouteName = routeName; string batchTemplate = String.IsNullOrEmpty(routePrefix) ? ODataRouteConstants.Batch : routePrefix + '/' + ODataRouteConstants.Batch; routes.MapHttpBatchRoute(routeName + "Batch", batchTemplate, batchHandler); } DefaultODataPathHandler odataPathHandler = pathHandler as DefaultODataPathHandler; if (odataPathHandler != null) { odataPathHandler.ResolverSetttings = configuration.GetResolverSettings(); } ODataPathRouteConstraint routeConstraint = new ODataPathRouteConstraint(pathHandler, model, routeName, routingConventions); ODataRoute route = new ODataRoute(routePrefix, routeConstraint); routes.Add(routeName, route); return route; }
public void HasRelaxedODataVersionConstraint_SetValue() { ODataRoute odataRoute = new ODataRoute(routePrefix: null, pathConstraint: null).HasRelaxedODataVersionConstraint(); Assert.True(((ODataVersionConstraint)odataRoute.Constraints[ODataRouteConstants.VersionConstraintName]).IsRelaxedMatch); }
// We need access to the root container but System.Web.OData.Extensions.HttpConfigurationExtensions.GetODataRootContainer is internal. public static IServiceProvider GetODataRootContainer(this HttpConfiguration configuration, ODataRoute oDataRoute) { Contract.Requires(configuration != null); Contract.Requires(oDataRoute != null); return (IServiceProvider)GetODataRootContainerMethod.Invoke(null, new object[] {configuration, oDataRoute.PathRouteConstraint.RouteName}); }
public SwaggerRoute(string template, ODataRoute oDataRoute) : this(template, oDataRoute, new PathItem()) { Contract.Requires(!string.IsNullOrWhiteSpace(template)); Contract.Requires(oDataRoute != null); }
public static ODataRoute MapODataServiceRoute(this HttpRouteCollection routes, string routeName, string routePrefix, IEdmModel model, IODataPathHandler pathHandler, IEnumerable<IODataRoutingConvention> routingConventions, ODataBatchHandler batchHandler) { if (routes == null) { throw Error.ArgumentNull("routes"); } if (!String.IsNullOrEmpty(routePrefix)) { int prefixLastIndex = routePrefix.Length - 1; if (routePrefix[prefixLastIndex] == '/') { // Remove the last trailing slash if it has one. routePrefix = routePrefix.Substring(0, routePrefix.Length - 1); } } if (batchHandler != null) { batchHandler.ODataRouteName = routeName; string batchTemplate = String.IsNullOrEmpty(routePrefix) ? ODataRouteConstants.Batch : routePrefix + '/' + ODataRouteConstants.Batch; routes.MapHttpBatchRoute(routeName + "Batch", batchTemplate, batchHandler); } ODataPathRouteConstraint routeConstraint = new ODataPathRouteConstraint(pathHandler, model, routeName, routingConventions); ODataRoute route = new ODataRoute(routePrefix, routeConstraint); routes.Add(routeName, route); return route; }
public void ODataVersionConstraint_DefaultIsRelaxedValueIsTrue() { ODataRoute odataRoute = new ODataRoute(routePrefix: null, pathConstraint: null); Assert.True(((ODataVersionConstraint)odataRoute.Constraints[ODataRouteConstants.VersionConstraintName]).IsRelaxedMatch); }
public void ODataVersionConstraint_DefaultValue() { ODataRoute odataRoute = new ODataRoute(routePrefix: null, pathConstraint: null); Assert.Equal(true, ((ODataVersionConstraint)odataRoute.Constraints[ODataRouteConstants.VersionConstraintName]).IsRelaxedMatch); }
public void SetODataVersionConstraint_SetValue(bool value) { ODataRoute odataRoute = new ODataRoute(routePrefix: null, pathConstraint: null).SetODataVersionConstraint(value); Assert.Equal(value, ((ODataVersionConstraint)odataRoute.Constraints[ODataRouteConstants.VersionConstraintName]).IsRelaxedMatch); }