AngularJS + ASP.NET MVC — можете ли вы использовать оба под /?

Я хочу обслуживать свой AngularJS SPA из «/», и по этой причине я отключил маршрут по умолчанию и использую

    // this action does not 'fire' due to Angular's routing...
    routes.MapRoute(
        name: "Test",
        url: "Test",
        defaults: new { controller = "Home", action = "Test" },
        namespaces: new[] { "My.WebApp.Controllers" }
    );

    // Index view has no layout and contains Angular SPA
    routes.MapRoute(
        name: "AngularJs-SPA",
        url: "{*catchall}",
        defaults: new { controller = "Home", action = "Index" },
        namespaces: new[] { "My.WebApp.Controllers" }
    );

Я также использую следующий блок конфигурации приложения angular

  .config(['$routeProvider', '$httpProvider', '$locationProvider', function ($routeProvider, $httpProvider, $locationProvider) {

      $routeProvider.otherwise({ redirectTo: '/404' });
      $httpProvider.defaults.headers.common["X-Requested-With"] = "XMLHttpRequest";
      $locationProvider.html5Mode(true);
  }])

Мой вопрос: могу ли я каким-то образом иметь обычную боковую страницу сервера, которая отвечает на действие MVC (в данном случае /Home/Test)? Проблема, которую я вижу, заключается в том, что Angular берет на себя маршрутизацию, и даже если я определяю дополнительный маршрут (до или после углового маршрута), Angular видит его как «иначе» маршрут...

Несколько (нежелательных) решений

  • укажите маршруты каждого углового приложения в MVC вместо {*catchall}
  • переместить angular spa в действие без полномочий root (например, /app)



Ответы (2)


Вы можете установить $window.location непосредственно из otherwise:

myApp
    .config(function($routeProvider, $locationProvider) {
        $routeProvider
            .when("/", {
                template: "<h1>Welcome!</h1>"
            })
            .otherwise({
                template: " ",
                controller: function($location, $window) {
                    $window.location.href = $location.path();
                    return false;
                }
            });
        $locationProvider.html5Mode(true);
    });
person dimirc    schedule 01.02.2014
comment
Я попробовал это, и это вызывает «бесконечный цикл», тогда как страница /Home/Test постоянно загружается с 200 OK.... - person zam6ak; 03.02.2014

Это может быть не совсем то, что вы ищете, но сейчас я это делаю, и это работает довольно хорошо.

Обратите внимание в .config, что я делаю html5Mode(false). Это сохраняет URL-адрес на той же странице и добавляет /#, который не позволяет маршрутизатору MVC вступить во владение. Это также означает, что вам нужно добавить этот /# в свои ссылки, чтобы убедиться, что вы можете добавить страницу в закладки и вернуться к ней (пройти через маршрутизацию на стороне сервера).

Кроме того, из-за того, что маршрутизатор MVC загружает страницы и ограничивает доступ к файлам CSHTML, я использую метод на стороне сервера для получения частичных представлений html. Некоторые из этих представлений используют HTML-помощники, поэтому я оставил их в виде файлов CSHTML вместо того, чтобы помещать их в неограниченную корзину статических представлений.

MVC-маршрутизация

        routes.MapRoute(
            name: "Direct",
            url: "{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );

-- Метод в домашнем (или базовом) контроллере

    public PartialViewResult GetPartial(string p)
    {
        return PartialView(string.Format("~/Views/Home/Partials/{0}.cshtml", p));
    }

-- Угловой код

app.config(function ($routeProvider, $locationProvider) {
    $locationProvider.html5Mode(false);

    $routeProvider
        .when("/", { templateUrl: "/GetPartial?p=Dashboard", controller: "DashboardController" })
        .when("/NewWidget/", { templateUrl: "/GetPartial?p=NewWidget", controller: "NewWidgetController" })
        .when("/Widget/:widgetId", { templateUrl: "/GetPartial?p=Widget", controller: "WidgetController" })
        .when("/Widget/Edit/:widgetId", { templateUrl: "/GetPartial?p=WidgetEdit", controller: "EditWidgetController" })
        .otherwise({ redirectTo: "/" });

});

app.controller('DashboardController', function ($scope, $http, $timeout, $q, $sce, $location, $routeParams) {

    $scope.SetPath = function (route) {
            if (!route) return;

            route = route.replace('/#', '');

            if (route[0] == '/')
                $location.path(route);
            else
                $location.path('/' + route);
        };
});

-- HTML

Вариант А)

<a ng-click="SetPath('/Widget?widgetId=w1234')">View Widget 1234</a>

Вариант Б)

<a href="/#/Widget?widgetId=w1234">View Widget 1234</a>
person Difinity    schedule 05.02.2014
comment
Обратите внимание в .config, что я делаю html5Mode(false)... К сожалению, это мешает мне... - person zam6ak; 05.02.2014