Building on Rishabh's answer, and using sergey's location.skipReload from this Angular Issue you can use the following to create a dialog on route-change, defer the url-change indefinitely (in effect 'cancelling' the route change), and rewrite the URL bar back to '/' without causing another reload:
//Override normal $location with this version that allows location.skipReload().path(...)
// Be aware that url bar can now get out of sync with what's being displayed, so take care when using skipReload to avoid this.
// From https://github.com/angular/angular.js/issues/1699#issuecomment-22511464
app.factory('location', [
  '$location',
  '$route',
  '$rootScope',
  function ($location, $route, $rootScope) {
    $location.skipReload = function () {
      var lastRoute = $route.current;
      var un = $rootScope.$on('$locationChangeSuccess', function () {
        $route.current = lastRoute;
        un();
      });
      return $location;
    };
    return $location;
  }
]);
app
  .config(['$routeProvider', function ($routeProvider) {
    $routeProvider
      .when('/home', {
        controller: 'HomeCtrl',
        templateUrl: 'Home/HomeView.html'
      })
      .when('/profile/:userId/changepwd', {
        template: ' ',
        controller: '',
        resolve: {
          data1: function($dialog, location, $q){
            $dialog.messageBox(title, msg, btns)
            .open()
            .then(function(result){
                //fires on modal close: rewrite url bar back to '/home'
                location.skipReload().path('/home');
                //Could also rewrite browser history here using location?
              });
            return $q.defer().promise; //Never resolves, so template ' ' and empty controller never actually get used.
          }
        }
      })
      .otherwise({
        redirectTo: '/'
      });
This feels like it leaks unresolved promises, and there may be a neater solution, but this worked for my purposes.