public async Task <IActionResult> RouteRequest(string startNode, string endNode, string routeType, TimeSpan startingTime)
        {
            try
            {
                // Get all student routes.
                AllStudentRoutes = await CongestionHelper.GenerateAllStudentRoutes(DissDatabaseContext, Pathfinder, MemoryCache, AppSettings.Accommodations);

                RouteRequestResponse response = new RouteRequestResponse();

                // If start and end are the same, return empty response.
                if (startNode == endNode)
                {
                    return(Ok(response));
                }

                // Get a list of possible start and end nodes that fulfil this request.
                List <string> starts = await RoutingHelper.GetMatchingIds(DissDatabaseContext, startNode, routeType[0].ToString());

                List <string> ends = await RoutingHelper.GetMatchingIds(DissDatabaseContext, endNode, routeType.Last().ToString());

                // Check we have a start location.
                if (starts.Count == 0)
                {
                    return(BadRequest("Could not find start points."));
                }

                // Check we have an end location.
                if (ends.Count == 0)
                {
                    return(BadRequest("Could not find end points"));
                }

                // Calculate all possible routes between all starts and all ends.
                // There is more than one start or end point - probably more efficient to calculate in parallel.
                if (starts.Count > 1 || ends.Count > 1)
                {
                    ConcurrentBag <Route> possibleRoutes         = new ConcurrentBag <Route>();
                    ConcurrentBag <Route> possibleAdjustedRoutes = new ConcurrentBag <Route>();
                    Parallel.ForEach(starts, startPoint =>
                    {
                        Parallel.ForEach(ends, destination =>
                        {
                            // Calculate route and add to possible.
                            possibleRoutes.Add(Pathfinder.BuildAStar(startPoint, destination));
                            possibleAdjustedRoutes.Add(Pathfinder.BuildAStar(startPoint, destination, AllStudentRoutes, startingTime));
                        });
                    });

                    // Find the shortest route from the possible routes.
                    response.NormalRoute   = RoutingHelper.FindTheBestRouteFromPossibleRoutes(possibleRoutes.ToList());
                    response.AdjustedRoute = RoutingHelper.FindTheBestRouteFromPossibleRoutes(possibleAdjustedRoutes.ToList());
                }
                else
                {
                    // Only one start and end point - only need to do this once, so avoid parallel overheads.
                    response.NormalRoute   = Pathfinder.BuildAStar(starts[0], ends[0]);
                    response.AdjustedRoute = Pathfinder.BuildAStar(starts[0], ends[0], AllStudentRoutes, startingTime);
                }

                // Adjust walking times based on congestion values.
                response.NormalRoute.CalculateAdjustedWalkingTime(AllStudentRoutes, startingTime);
                response.AdjustedRoute.CalculateAdjustedWalkingTime(AllStudentRoutes, startingTime);

                if (response.AdjustedRoute.WalkingTimeSeconds == response.NormalRoute.WalkingTimeSeconds)
                {
                    // Both routes are the same, remove the adjusted route - there was likely no congestion.
                    response.AdjustedRoute = new Route();
                }

                return(Ok(response));
            }
            catch (Exception exception)
            {
                return(StatusCode(500, exception.Message));
            }
        }