Beispiel #1
0
        private void GetCRMUser(ref ServiceObject so)
        {
            Method         meth     = so.Methods[0];
            BingMapsHelper bmHelper = new BingMapsHelper();

            RouteDirections SearchResults = new RouteDirections();

            try
            {
                if (meth.Name.ToLower().Equals("getdirectionsbycoordinates"))
                {
                    SearchResults = bmHelper.GetDirectionsByCoordinates(so.Properties["RouteCoordinates"].Value.ToString(), NotNull(so.Properties["RouteTravelMode"].Value), NotNull(so.Properties["RouteTrafficUsage"].Value), NotNull(so.Properties["RouteOptimisation"].Value), GetConfigPropertyValue("BingMapsKey"));
                }
                else
                {
                    SearchResults = bmHelper.GetDirectionsByLocations(so.Properties["SearchLocation"].Value.ToString(), NotNull(so.Properties["RouteTravelMode"].Value), NotNull(so.Properties["RouteTrafficUsage"].Value), NotNull(so.Properties["RouteOptimisation"].Value), GetConfigPropertyValue("BingMapsKey"));
                }

                so.Properties.InitResultTable();
                so.Properties["RouteDirections"].Value    = SearchResults.Directions;
                so.Properties["RouteTotalDistance"].Value = SearchResults.TotalDistance;

                so.Properties.BindPropertiesToResultTable();
            }
            catch (Exception ex)
            {
                throw;
            }
        }
        public async Task <DialogTurnResult> GetRoutesToDestination(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                var state = await Accessor.GetAsync(sc.Context);

                var service         = ServiceManager.InitRoutingMapsService(Settings);
                var routeDirections = new RouteDirections();
                var cards           = new List <Card>();

                if (state.Destination == null || !state.CheckForValidCurrentCoordinates())
                {
                    // should not happen
                    await sc.Context.SendActivityAsync(ResponseManager.GetResponse(RouteResponses.MissingActiveLocationErrorMessage));

                    return(await sc.EndDialogAsync());
                }

                if (!string.IsNullOrEmpty(state.RouteType))
                {
                    routeDirections = await service.GetRouteDirectionsToDestinationAsync(state.CurrentCoordinates.Latitude, state.CurrentCoordinates.Longitude, state.Destination.Geolocation.Latitude, state.Destination.Geolocation.Longitude, state.RouteType);

                    cards = await GetRouteDirectionsViewCards(sc, routeDirections, service);
                }
                else
                {
                    routeDirections = await service.GetRouteDirectionsToDestinationAsync(state.CurrentCoordinates.Latitude, state.CurrentCoordinates.Longitude, state.Destination.Geolocation.Latitude, state.Destination.Geolocation.Longitude);

                    cards = await GetRouteDirectionsViewCards(sc, routeDirections, service);
                }

                if (cards.Count() == 0)
                {
                    var replyMessage = ResponseManager.GetResponse(POISharedResponses.NoRouteFound);
                    await sc.Context.SendActivityAsync(replyMessage);

                    return(await sc.EndDialogAsync());
                }
                else if (cards.Count() == 1)
                {
                    return(await sc.PromptAsync(Actions.StartNavigationPrompt, new PromptOptions { Prompt = ResponseManager.GetCardResponse(cards[0]) }));
                }
                else
                {
                    var options = GetRoutesPrompt(POISharedResponses.MultipleRoutesFound, cards);

                    return(await sc.PromptAsync(Actions.StartNavigationPrompt, options));
                }
            }
            catch (Exception ex)
            {
                await HandleDialogExceptions(sc, ex);

                return(new DialogTurnResult(DialogTurnStatus.Cancelled, CommonUtil.DialogTurnResultCancelAllDialogs));
            }
        }
Beispiel #3
0
        protected async Task GetRouteDirectionsViewCards(DialogContext sc, RouteDirections routeDirections)
        {
            var routes = routeDirections.Routes;
            var state  = await Accessor.GetAsync(sc.Context);

            var cardData = new List <RouteDirectionsModelCardData>();
            var routeId  = 0;

            if (routes != null)
            {
                state.FoundRoutes = routes.ToList();

                foreach (var route in routes)
                {
                    var travelTimeSpan  = TimeSpan.FromSeconds(route.Summary.TravelTimeInSeconds);
                    var trafficTimeSpan = TimeSpan.FromSeconds(route.Summary.TrafficDelayInSeconds);

                    var routeDirectionsModel = new RouteDirectionsModelCardData()
                    {
                        Location     = state.ActiveLocation.Name,
                        TravelTime   = GetFormattedTravelTimeSpanString(travelTimeSpan),
                        TrafficDelay = GetFormattedTrafficDelayString(trafficTimeSpan),
                        RouteId      = routeId,
                    };

                    cardData.Add(routeDirectionsModel);
                    routeId++;
                }

                if (cardData.Count() > 1)
                {
                    var cards = new List <Card>();
                    foreach (var data in cardData)
                    {
                        cards.Add(new Card("RouteDirectionsViewCard", data));
                    }

                    var replyMessage = ResponseManager.GetCardResponse(POISharedResponses.MultipleRoutesFound, cards);
                    await sc.Context.SendActivityAsync(replyMessage);
                }
                else
                {
                    var card         = new Card("RouteDirectionsViewCardNoGetStartedButton", cardData.SingleOrDefault());
                    var replyMessage = ResponseManager.GetCardResponse(POISharedResponses.SingleRouteFound, card);
                    await sc.Context.SendActivityAsync(replyMessage);
                }
            }
            else
            {
                var replyMessage = ResponseManager.GetResponse(POISharedResponses.NoLocationsFound);
                await sc.Context.SendActivityAsync(replyMessage);
            }
        }
Beispiel #4
0
        public async Task <DialogTurnResult> GetRoutesToActiveLocation(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                var state = await Accessor.GetAsync(sc.Context);

                var service         = ServiceManager.InitMapsService(GetAzureMapsKey());
                var routeDirections = new RouteDirections();

                state.CheckForValidCurrentCoordinates();

                if (state.ActiveLocation == null)
                {
                    // No ActiveLocation found
                    return(await sc.PromptAsync(Action.Prompt, new PromptOptions { Prompt = sc.Context.Activity.CreateReply(RouteResponses.MissingActiveLocationErrorMessage, ResponseBuilder) }));
                }

                if (!string.IsNullOrEmpty(state.SearchDescriptor))
                {
                    routeDirections = await service.GetRouteDirectionsAsync(state.CurrentCoordinates.Latitude, state.CurrentCoordinates.Longitude, state.ActiveLocation.Point.Coordinates[0], state.ActiveLocation.Point.Coordinates[1], state.SearchDescriptor);

                    await GetRouteDirectionsViewCards(sc, routeDirections);
                }
                else
                {
                    routeDirections = await service.GetRouteDirectionsAsync(state.CurrentCoordinates.Latitude, state.CurrentCoordinates.Longitude, state.ActiveLocation.Point.Coordinates[0], state.ActiveLocation.Point.Coordinates[1]);

                    await GetRouteDirectionsViewCards(sc, routeDirections);
                }

                if (routeDirections?.Routes?.ToList().Count == 1)
                {
                    return(await sc.PromptAsync(Action.ConfirmPrompt, new PromptOptions { Prompt = sc.Context.Activity.CreateReply(RouteResponses.PromptToStartRoute, ResponseBuilder) }));
                }

                state.ClearLuisResults();

                return(await sc.EndDialogAsync());
            }
            catch
            {
                await HandleDialogException(sc);

                throw;
            }
        }
        protected async Task GetRouteDirectionsViewCards(DialogContext sc, RouteDirections routeDirections)
        {
            var routes = routeDirections.Routes;
            var state  = await Accessor.GetAsync(sc.Context);

            var cardsData = new List <RouteDirectionsModelCardData>();
            var routeId   = 0;

            if (routes != null)
            {
                state.FoundRoutes = routes.ToList();

                foreach (var route in routes)
                {
                    var travelTimeSpan  = TimeSpan.FromSeconds(route.Summary.TravelTimeInSeconds);
                    var trafficTimeSpan = TimeSpan.FromSeconds(route.Summary.TrafficDelayInSeconds);

                    var routeDirectionsModel = new RouteDirectionsModelCardData()
                    {
                        Location     = state.ActiveLocation.Name,
                        TravelTime   = GetFormattedTravelTimeSpanString(travelTimeSpan),
                        TrafficDelay = GetFormattedTrafficDelayString(trafficTimeSpan),
                        RouteId      = routeId,
                    };

                    cardsData.Add(routeDirectionsModel);
                    routeId++;
                }

                if (cardsData.Count() > 1)
                {
                    var replyMessage = sc.Context.Activity.CreateAdaptiveCardGroupReply(POISharedResponses.MultipleRoutesFound, "Dialogs/Shared/Resources/Cards/RouteDirectionsViewCard.json", AttachmentLayoutTypes.Carousel, cardsData);
                    await sc.Context.SendActivityAsync(replyMessage);
                }
                else
                {
                    var replyMessage = sc.Context.Activity.CreateAdaptiveCardReply(POISharedResponses.SingleRouteFound, "Dialogs/Shared/Resources/Cards/RouteDirectionsViewCardNoGetStartedButton.json", cardsData.SingleOrDefault());
                    await sc.Context.SendActivityAsync(replyMessage);
                }
            }
            else
            {
                var replyMessage = sc.Context.Activity.CreateReply(POISharedResponses.NoLocationsFound, ResponseBuilder);
                await sc.Context.SendActivityAsync(replyMessage);
            }
        }
Beispiel #6
0
        public async Task <DialogTurnResult> GetRoutesToDestination(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                var state = await Accessor.GetAsync(sc.Context);

                var service         = ServiceManager.InitRoutingMapsService(Services);
                var routeDirections = new RouteDirections();

                state.CheckForValidCurrentCoordinates();

                if (state.Destination == null)
                {
                    // No ActiveLocation found
                    return(await sc.PromptAsync(Actions.Prompt, new PromptOptions { Prompt = ResponseManager.GetResponse(RouteResponses.MissingActiveLocationErrorMessage) }));
                }

                if (!string.IsNullOrEmpty(state.RouteType))
                {
                    routeDirections = await service.GetRouteDirectionsToDestinationAsync(state.CurrentCoordinates.Latitude, state.CurrentCoordinates.Longitude, state.Destination.Geolocation.Latitude, state.Destination.Geolocation.Longitude, state.RouteType);

                    await GetRouteDirectionsViewCards(sc, routeDirections);
                }
                else
                {
                    routeDirections = await service.GetRouteDirectionsToDestinationAsync(state.CurrentCoordinates.Latitude, state.CurrentCoordinates.Longitude, state.Destination.Geolocation.Latitude, state.Destination.Geolocation.Longitude);

                    await GetRouteDirectionsViewCards(sc, routeDirections);
                }

                if (routeDirections?.Routes?.ToList().Count == 1)
                {
                    return(await sc.PromptAsync(Actions.ConfirmPrompt, new PromptOptions { Prompt = ResponseManager.GetResponse(RouteResponses.PromptToStartRoute) }));
                }

                state.ClearLuisResults();

                return(await sc.EndDialogAsync());
            }
            catch (Exception ex)
            {
                await HandleDialogExceptions(sc, ex);

                return(new DialogTurnResult(DialogTurnStatus.Cancelled, CommonUtil.DialogTurnResultCancelAllDialogs));
            }
        }
Beispiel #7
0
        /// <summary>
        /// Get route directions response from Azure Maps.
        /// </summary>
        /// <returns>RouteDirections.</returns>
        private async Task <RouteDirections> GetRouteDirectionsAsync(string url)
        {
            var response = await httpClient.GetAsync(url);

            var apiResponse = new RouteDirections();

            // TODO when it returns 400 for uncovered areas, we return no route instead. For other unsuccessful codes, exception is thrown as usual
            if (response.StatusCode != System.Net.HttpStatusCode.BadRequest)
            {
                response = response.EnsureSuccessStatusCode();
                var content = await response.Content.ReadAsStringAsync();

                apiResponse = JsonConvert.DeserializeObject <RouteDirections>(content);
            }

            apiResponse.Provider = Provider;

            return(apiResponse);
        }
Beispiel #8
0
        /// <summary>
        /// Processing results of solve operation.
        /// </summary>
        /// <param name="batchResponse">Response from solver.</param>
        /// <returns>SolveResult.</returns>
        /// <exception cref="RouteException">In case of invalid GPFeature mapping.
        /// </exception>
        private SolveResult _ProcessSolveResult(BatchRouteSolveResponse batchResponse)
        {
            Debug.Assert(batchResponse != null);
            Debug.Assert(batchResponse.Responses != null);

            List <RouteMessage> messages = new List <RouteMessage>();

            foreach (RouteSolveResponse resp in batchResponse.Responses)
            {
                if (resp.Directions != null &&
                    resp.Directions.Length > 0)
                {
                    // We use one request per route, so we get first directions element.
                    RouteDirections routeDirs = resp.Directions[0];

                    // Route id.
                    Guid routeId = new Guid(routeDirs.RouteName);

                    // Find route.
                    Route route = _FindRoute(routeId);
                    if (route == null)
                    {
                        throw new RouteException(Properties.Messages.Error_InvalidGPFeatureMapping);
                    }

                    // Set directions.
                    _SetDirections(route.Stops, routeDirs.Features);
                }

                if (resp.Messages != null)
                {
                    messages.AddRange(resp.Messages);
                }
            }

            return(_CreateSolveResult(messages.ToArray()));
        }
Beispiel #9
0
        protected async Task GetRouteDirectionsViewCards(DialogContext sc, RouteDirections routeDirections)
        {
            var routes = routeDirections.Routes;
            var state  = await Accessor.GetAsync(sc.Context);

            var cardData = new List <RouteDirectionsModelCardData>();
            var routeId  = 0;

            if (routes != null)
            {
                state.FoundRoutes = routes.ToList();

                var destination = state.Destination;

                foreach (var route in routes)
                {
                    var travelTimeSpan  = TimeSpan.FromSeconds(route.Summary.TravelTimeInSeconds);
                    var trafficTimeSpan = TimeSpan.FromSeconds(route.Summary.TrafficDelayInSeconds);

                    // Set card data with formatted time strings and distance converted to miles
                    var routeDirectionsModel = new RouteDirectionsModelCardData()
                    {
                        Name             = destination.Name,
                        Street           = destination.Street,
                        City             = destination.City,
                        AvailableDetails = destination.AvailableDetails,
                        Hours            = destination.Hours,
                        ImageUrl         = destination.ImageUrl,
                        TravelTime       = GetShortTravelTimespanString(travelTimeSpan),
                        DelayStatus      = GetFormattedTrafficDelayString(trafficTimeSpan),
                        Distance         = $"{(route.Summary.LengthInMeters / 1609.344).ToString("N1")} {PointOfInterestSharedStrings.MILES_ABBREVIATION}",
                        ETA              = route.Summary.ArrivalTime.ToShortTimeString(),
                        TravelTimeSpeak  = GetFormattedTravelTimeSpanString(travelTimeSpan),
                        TravelDelaySpeak = GetFormattedTrafficDelayString(trafficTimeSpan)
                    };

                    cardData.Add(routeDirectionsModel);
                    routeId++;
                }

                if (cardData.Count() > 1)
                {
                    var cards = new List <Card>();
                    foreach (var data in cardData)
                    {
                        cards.Add(new Card("RouteDirectionsViewCard", data));
                    }

                    var replyMessage = ResponseManager.GetCardResponse(POISharedResponses.MultipleRoutesFound, cards);
                    replyMessage.Speak = ResponseUtility.BuildSpeechFriendlyPoIResponse(replyMessage);
                    await sc.Context.SendActivityAsync(replyMessage);
                }
                else
                {
                    var card         = new Card("RouteDirectionsViewCard", cardData.SingleOrDefault());
                    var replyMessage = ResponseManager.GetCardResponse(POISharedResponses.SingleRouteFound, card);
                    replyMessage.Speak = ResponseUtility.BuildSpeechFriendlyPoIResponse(replyMessage);
                    await sc.Context.SendActivityAsync(replyMessage);
                }
            }
            else
            {
                var replyMessage = ResponseManager.GetResponse(POISharedResponses.NoLocationsFound);
                await sc.Context.SendActivityAsync(replyMessage);
            }
        }
        protected async Task <List <Card> > GetRouteDirectionsViewCards(DialogContext sc, RouteDirections routeDirections, IGeoSpatialService service)
        {
            var routes = routeDirections.Routes;
            var state  = await Accessor.GetAsync(sc.Context);

            var cardData = new List <RouteDirectionsModel>();
            var cards    = new List <Card>();
            var routeId  = 0;

            if (routes != null)
            {
                state.FoundRoutes = routes.Select(route => route.Summary).ToList();

                var destination = state.Destination;
                destination.Provider.Add(routeDirections.Provider);

                foreach (var route in routes)
                {
                    var travelTimeSpan  = TimeSpan.FromSeconds(route.Summary.TravelTimeInSeconds);
                    var trafficTimeSpan = TimeSpan.FromSeconds(route.Summary.TrafficDelayInSeconds);

                    // Set card data with formatted time strings and distance converted to miles
                    var routeDirectionsModel = new RouteDirectionsModel()
                    {
                        Name                    = destination.Name,
                        Address                 = destination.Address,
                        AvailableDetails        = destination.AvailableDetails,
                        Hours                   = destination.Hours,
                        PointOfInterestImageUrl = await service.GetRouteImageAsync(destination, route, ImageSize.RouteWidth, ImageSize.RouteHeight),
                        TravelTime              = GetShortTravelTimespanString(travelTimeSpan),
                        DelayStatus             = GetFormattedTrafficDelayString(trafficTimeSpan),
                        Distance                = $"{(route.Summary.LengthInMeters / 1609.344).ToString("N1")} {PointOfInterestSharedStrings.MILES_ABBREVIATION}",
                        ETA                   = route.Summary.ArrivalTime.ToShortTimeString(),
                        TravelTimeSpeak       = GetFormattedTravelTimeSpanString(travelTimeSpan),
                        TravelDelaySpeak      = GetFormattedTrafficDelayString(trafficTimeSpan),
                        ProviderDisplayText   = destination.GenerateProviderDisplayText(),
                        Speak                 = GetFormattedTravelTimeSpanString(travelTimeSpan),
                        ActionStartNavigation = PointOfInterestSharedStrings.START,
                        CardTitle             = PointOfInterestSharedStrings.CARD_TITLE
                    };

                    cardData.Add(routeDirectionsModel);
                    routeId++;
                }

                foreach (var data in cardData)
                {
                    cards.Add(new Card(GetDivergedCardName(sc.Context, "PointOfInterestDetailsWithRoute"), data));
                }
            }

            return(cards);
        }
        protected async Task <List <Card> > GetRouteDirectionsViewCards(DialogContext sc, RouteDirections routeDirections)
        {
            var routes = routeDirections.Routes;
            var state  = await Accessor.GetAsync(sc.Context);

            var cardData = new List <RouteDirectionsModel>();
            var cards    = new List <Card>();
            var routeId  = 0;

            if (routes != null)
            {
                state.FoundRoutes = routes.ToList();

                var destination = state.Destination;

                foreach (var route in routes)
                {
                    var travelTimeSpan  = TimeSpan.FromSeconds(route.Summary.TravelTimeInSeconds);
                    var trafficTimeSpan = TimeSpan.FromSeconds(route.Summary.TrafficDelayInSeconds);

                    destination.Provider.Add(routeDirections.Provider);

                    // Set card data with formatted time strings and distance converted to miles
                    var routeDirectionsModel = new RouteDirectionsModel()
                    {
                        Name                    = destination.Name,
                        Address                 = destination.Address,
                        AvailableDetails        = destination.AvailableDetails,
                        Hours                   = destination.Hours,
                        PointOfInterestImageUrl = destination.PointOfInterestImageUrl,
                        TravelTime              = GetShortTravelTimespanString(travelTimeSpan),
                        DelayStatus             = GetFormattedTrafficDelayString(trafficTimeSpan),
                        Distance                = $"{(route.Summary.LengthInMeters / 1609.344).ToString("N1")} {PointOfInterestSharedStrings.MILES_ABBREVIATION}",
                        ETA                 = route.Summary.ArrivalTime.ToShortTimeString(),
                        TravelTimeSpeak     = GetFormattedTravelTimeSpanString(travelTimeSpan),
                        TravelDelaySpeak    = GetFormattedTrafficDelayString(trafficTimeSpan),
                        ProviderDisplayText = string.Format($"{PointOfInterestSharedStrings.POWERED_BY} **{{0}}**", destination.Provider.Aggregate((j, k) => j + " & " + k).ToString()),
                        Speak               = GetFormattedTravelTimeSpanString(travelTimeSpan)
                    };

                    cardData.Add(routeDirectionsModel);
                    routeId++;
                }

                foreach (var data in cardData)
                {
                    cards.Add(new Card("PointOfInterestDetailsWithRoute", data));
                }
            }

            return(cards);
        }
        public async Task <DialogTurnResult> GetRoutesToDestination(WaterfallStepContext sc, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                var state = await Accessor.GetAsync(sc.Context);

                var service         = ServiceManager.InitRoutingMapsService(Settings);
                var routeDirections = new RouteDirections();
                var cards           = new List <Card>();

                state.CheckForValidCurrentCoordinates();

                if (state.Destination == null)
                {
                    // No ActiveLocation found
                    return(await sc.PromptAsync(Actions.Prompt, new PromptOptions { Prompt = ResponseManager.GetResponse(RouteResponses.MissingActiveLocationErrorMessage) }));
                }

                if (!string.IsNullOrEmpty(state.RouteType))
                {
                    routeDirections = await service.GetRouteDirectionsToDestinationAsync(state.CurrentCoordinates.Latitude, state.CurrentCoordinates.Longitude, state.Destination.Geolocation.Latitude, state.Destination.Geolocation.Longitude, state.RouteType);

                    cards = await GetRouteDirectionsViewCards(sc, routeDirections);
                }
                else
                {
                    routeDirections = await service.GetRouteDirectionsToDestinationAsync(state.CurrentCoordinates.Latitude, state.CurrentCoordinates.Longitude, state.Destination.Geolocation.Latitude, state.Destination.Geolocation.Longitude);

                    cards = await GetRouteDirectionsViewCards(sc, routeDirections);
                }

                if (cards.Count() == 0)
                {
                    var replyMessage = ResponseManager.GetResponse(POISharedResponses.NoLocationsFound);
                    await sc.Context.SendActivityAsync(replyMessage);
                }
                else if (cards.Count() == 1)
                {
                    var options = new PromptOptions
                    {
                        Prompt = ResponseManager.GetCardResponse(POISharedResponses.SingleRouteFound, cards)
                    };

                    // Workaround. In teams, HeroCard will be used for prompt and adaptive card could not be shown. So send them separatly
                    if (Channel.GetChannelId(sc.Context) == Channels.Msteams)
                    {
                        await sc.Context.SendActivityAsync(options.Prompt);

                        options.Prompt = null;
                    }

                    return(await sc.PromptAsync(Actions.ConfirmPrompt, options));
                }

                state.ClearLuisResults();

                return(await sc.EndDialogAsync());
            }
            catch (Exception ex)
            {
                await HandleDialogExceptions(sc, ex);

                return(new DialogTurnResult(DialogTurnStatus.Cancelled, CommonUtil.DialogTurnResultCancelAllDialogs));
            }
        }
        private void GetCRMUser(ref ServiceObject so)
        {
            Method meth = so.Methods[0];
            BingMapsHelper bmHelper = new BingMapsHelper();

            RouteDirections SearchResults = new RouteDirections();

            try
            {
                if (meth.Name.ToLower().Equals("getdirectionsbycoordinates"))
                {
                    SearchResults = bmHelper.GetDirectionsByCoordinates(so.Properties["RouteCoordinates"].Value.ToString(), NotNull(so.Properties["RouteTravelMode"].Value), NotNull(so.Properties["RouteTrafficUsage"].Value), NotNull(so.Properties["RouteOptimisation"].Value), GetConfigPropertyValue("BingMapsKey"));
                }
                else
                {
                    SearchResults = bmHelper.GetDirectionsByLocations(so.Properties["SearchLocation"].Value.ToString(), NotNull(so.Properties["RouteTravelMode"].Value), NotNull(so.Properties["RouteTrafficUsage"].Value), NotNull(so.Properties["RouteOptimisation"].Value), GetConfigPropertyValue("BingMapsKey"));
                }

                so.Properties.InitResultTable();
                so.Properties["RouteDirections"].Value = SearchResults.Directions;
                so.Properties["RouteTotalDistance"].Value = SearchResults.TotalDistance;

                so.Properties.BindPropertiesToResultTable();

            }
            catch (Exception ex)
            {
                throw;
            }
        }