public void ConfigureRoutes(HttpConfiguration config, bool useSchoolYear) { Preconditions.ThrowIfNull(config, nameof(config)); string compositeRouteBase = "composites/v{compositeVersion}/" + (useSchoolYear ? "{schoolYearFromRoute}/" : string.Empty) + "{organizationCode}/{compositeCategory}/"; // Construct the route constraint pattern for the composite categories defined. var compositeCategoryNames = _compositesMetadataProvider.GetAllCategories() .Select(x => x.Name) .ToList(); // Don't add routes for composites, if none exit. if (!compositeCategoryNames.Any()) { return; } string allCompositeCategoriesConstraintExpression = $@"^(?i)({string.Join("|", compositeCategoryNames)})$"; // Define default route for all composites config.Routes.MapHttpRoute( name: "Composites", routeTemplate: compositeRouteBase + "{compositeName}/{id}", defaults: new { id = RouteParameter.Optional, controller = "CompositeResource" }, constraints: useSchoolYear ? (object)new { compositeCategory = allCompositeCategoriesConstraintExpression, schoolYearFromRoute = @"^\d{4}$" } : new { compositeCategory = allCompositeCategoriesConstraintExpression } ); var routeMetadataGroupedByCompositeCategory = _compositesMetadataProvider.GetAllRoutes(); foreach (var routeGrouping in routeMetadataGroupedByCompositeCategory) { string categoryName = routeGrouping.Key.Name; int routeNumber = 1; foreach (var routeElt in routeGrouping.Value) { string relativeRouteTemplate = routeElt.AttributeValue("relativeRouteTemplate") .TrimStart('/'); config.Routes.MapHttpRoute( name: $"{categoryName}Composites{routeNumber++}", routeTemplate: compositeRouteBase + relativeRouteTemplate, defaults: new { controller = "CompositeResource" }, constraints: new { compositeCategory = categoryName }); } } }
public void Apply(ApplicationModel application) { var controller = application.Controllers.FirstOrDefault( x => x.ControllerType == typeof(CompositeResourceController).GetTypeInfo()); // composites/v{compositeVersion}/{school year if year specific}/{organizationCode}/{compositeCategoryName (regex constraint}/{compositeName}/{id?} // the composite category is constrained by a regex expression // the id is optional // the attribute on the controller is composites if (controller != null) { var defaultRouteSuffix = new AttributeRouteModel { Template = CreateRouteTemplate() + "{compositeName}/{id?}" }; // the composite controller has only one selector and if more are added this should break var selector = controller.Selectors.SingleOrDefault(); if (selector.AttributeRouteModel != null) { // composites have children routes that need to be added to the controller. var routeMetadataGroupedByCompositeCategory = _compositesMetadataProvider.GetAllRoutes(); foreach (var routeGrouping in routeMetadataGroupedByCompositeCategory) { foreach (var routeElt in routeGrouping.Value) { string relativeRouteTemplate = routeElt.AttributeValue("relativeRouteTemplate") .TrimStart('/'); var routeSuffix = new AttributeRouteModel { Template = CreateRouteTemplate() + relativeRouteTemplate }; var childSelector = new SelectorModel { AttributeRouteModel = AttributeRouteModel.CombineAttributeRouteModel( selector.AttributeRouteModel, routeSuffix) }; controller.Selectors.Add(childSelector); } } // set the base selector with the correct route selector.AttributeRouteModel = AttributeRouteModel.CombineAttributeRouteModel( selector.AttributeRouteModel, defaultRouteSuffix); } } string CreateRouteTemplate() { string template = $"v{ApiVersionConstants.Composite}/"; if (_apiSettings.GetApiMode() == ApiMode.YearSpecific) { template += RouteConstants.SchoolYearFromRoute; } if (_apiSettings.GetApiMode() == ApiMode.InstanceYearSpecific) { template += RouteConstants.InstanceIdFromRoute; template += RouteConstants.SchoolYearFromRoute; } var compositeCategoryNames = _compositesMetadataProvider .GetAllCategories() .Select(x => x.Name) .ToList <string>(); string allCompositeCategoriesConstraintExpression = $@"^(?i)({string.Join("|", compositeCategoryNames)})$"; string categoryName = "{organizationCode}/{compositeCategory}/"; template += categoryName; return(template); } }