本文介绍了如何在 ASP.NET MVC 中定义 Angular Routing的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对在 Asp.Net MVC 应用程序中使用 Angular 的路由感到有些困惑.

为了理解我的问题,我将展示我的应用程序的当前代码:

Index.cshtml:

...@Styles.Render("~/Content/css")@Scripts.Render("~/bundles/modernizr")@Scripts.Render("~/bundles/jquery")@Scripts.Render("~/bundles/bootstrap")<身体><div class="navbar navbar-default navbar-fixed-top"><div class="容器"><div class="navbar-collapse collapse glyphicons pull-right"><ul class="nav navbar-nav"><li ng-class="{active:isActive == '/test1'}"><a href="#/test1">Test1</a><li ng-class="{active:isActive == '/test2'}"><a href="#/test2">Test2</a>

<div class="container body-content"><div ng-view></div>

@Scripts.Render("~/bundles/angular")@Scripts.Render("~/bundles/app")

HomeController (ASP.NET):

命名空间 Tests.Controllers{公共类 HomeController : 控制器{公共 ActionResult 索引(){返回 PartialView();}公共 ActionResult 测试 1(){返回 PartialView();}公共 ActionResult Test2(){返回 PartialView();}}}

我的 Angular 模块:

角度.module('测试', ['ngRoute']).config(配置).run(['$rootScope', '$route', '$location', function($rootScope, $route, $location) {$rootScope.$on('$routeChangeSuccess', function(event, currRoute, prevRoute) {$rootScope.title = $route.current.title;});var path = function() {返回 $location.path();};$rootScope.$watch(path, function(newPath, oldPath) {$rootScope.isActive = newPath;});}]);config.$inject = ['$routeProvider'];功能配置($routeProvider){$routeProvider.when('/test1', {templateUrl: '/Home/Test1',isActive: 'test1'}).when('/test2', {templateUrl: '/Home/Test2',isActive: 'test2'}).除此以外({重定向到:'/'});}

输出网址如下所示:localhost/Home/Index#/test1

问题:

我需要在 HomeController 中定义 Actions 吗?为什么?我以为我只需要 ActionResult 索引,因为我使用了 PartialView()...我怎样才能获得以下 URL:localhost/test1 当我点击菜单 Test1 时?

解决方案

除了@Andiih 在他的回答中所说的.Angular 路由库旨在处理您的 Angular 路由 前端 控制器之间.

您似乎混合了 AngularASP.NET MVC 路由,这与您期望 2 的工作方式相同.你的基本路由是 localhost/Home/Index# 从那时起 Angular 将它自己的(子)路由附加到基本的 URL,导致您看到的输出 URL.

即使根据需要在 MVCAngular 路由和控制器之间跳转可能是可行的,但这将是一个比我假设的更复杂的场景旨在实现.此外,我过去从未需要达到那种程度.

总结当前会发生什么:

如果您必须离开您的 Index.cshtml根"页面,您实际上会离开您当前的 Angular 应用程序...或导航 不同的应用程序...根据解决方案结构,您甚至可以为每个单独的页面使用不同的 JavaScript MV* 框架...但这太疯狂了.

...但我怀疑这是你在这个阶段想要的,所以为了简单起见,让我们坚持假设你只有一个 ASP.Net MVC Route/Page,而你只是纯粹的想要在 Angular 路由之间导航,并以某种方式从后端 .NET 服务向 Angular 路由或页面提供数据.

因此,您似乎可能会错过每个框架在您当前拥有的堆栈中所扮演的角色之间的联系.(我会尽量澄清)

例如:

如果您查看一个(非常通用的)整体解决方案结构,它可能如下所示.

 - css- bootstrap.css//所有 3rd 方 css 在这里- 库- angular.js//所有 3rd 方 js 库在这里- angular-ui-router.js- 控制器- RootController.cs//这是你的 HomeController.//它有效地用于交付"根视图//您的核心/基本页面缺乏更好的术语- 意见- RootView.cshtml//参见下面的代码 RootView.cshtml,//这定义了您的应用程序布局"//以及您交付捆绑包的地方,//使用服务器端身份验证等.- 网络接口- test1Api.cs//访问 test1 数据或服务器端进程- test2Api.cs//等等..- 应用程序- 页面- 家- 测试 1- test1Ctrl.js- test1View.html- 测试1.css- 测试2- test2Ctrl.js- test2View.html- test2.css- 服务- someRandomSvc.js- resourceSvc.js//这是你使用你的//.NET 后端 API.例如:test1Api &test2Api 等.- 应用程序.js- app.routes.js- 等等...

RootView.cshtml 在服务器端构建,从而允许您使用 .NET 捆绑Asp.NET Auth 等.无论如何,整个页面将充当 Angular 应用程序的外壳,整个前端应用程序",因此在该页面的上下文中运行.

RootView.cshtml

@Styles.Render("~/content/3rdPartyCSS")@Styles.Render("~/content/appSpecificCSS")<身体><div class="navbar navbar-default navbar-fixed-top"><div class="容器"><div class="navbar-collapse collapse glyphicons pull-right"><ul class="nav navbar-nav"><li><a ui-sref="home">Home</a></li><li><a ui-sref="test1">Test1</a></li><li><a ui-sref="test2">Test2</a></li>

<div class="container body-content"><div ng-view></div>

@Scripts.Render("~/bundles/3rdPartyJS")@Scripts.Render("~/bundles/appSpecificJS")

你只需要一个 ASP.Net MVC Route,正如我之前所说,你不会离开它(至少对于这个应用程序)

RootController.cs

命名空间 Tests.Controllers{公共类 RootController :控制器{公共 ActionResult RootView(){//正如我之前在另一篇文章中提到的,//我们返回一个部分以避免使用_layout.cshtml//因为我们的 RootView 充当 angular 应用程序的布局.//(它会引入另一层不需要的嵌套)返回 PartialView();}}}

...但您将需要多个 Angular 路由.

app.routes.js

var app = angular.module('Tests');app.config(['$stateprovider', function($stateprovider) {$州提供者.state('home', { url: '', templateUrl: 'app/pages/home/homeView.html' }]).state('test1', { url: '/test1', templateUrl: 'app/pages/test1/test1View.html'}).state('test2', { url: '/test2', templateUrl: 'app/pages/test2/test2View.html'});}]);

然后您将通过 WebAPI 端点,您需要通过类似ngResource,然后您将在 Angular 控制器中使用它.>

testXView.html

<div ng-controller="testXCtrl as test">{{ test.something }}</div>

testXCtrl.js

var app = angular.module('Test');app.controller('testXCtrl',['resourceSvc', function(resourceSvc) {resourceSvc.getSomeData().then(function(data) {this.something = 数据;//.. 或任何漂浮你的船的东西:P})}]);

注意.

  1. 使用这个约定和 angular .something(['service', function(service) { }]); 是使代码 分钟安全.(所以看到的时候不要太害怕)
  2. 在我的示例中,我使用了一个名为 angular-ui-router 的路由库,我建议你看看它,如果你在这个阶段有选择的自由......但相同的原则适用于 ngRoute 解决方案.

I'm a bit confused about using the routing of Angular within an Asp.Net MVC app.

To understand my question I will shown the currently code of my app:

Index.cshtml:

<head>
    ...
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
</head>
<body>
    <div class="navbar navbar-default navbar-fixed-top">
        <div class="container">
            <div class="navbar-collapse collapse glyphicons pull-right">
                <ul class="nav navbar-nav">
                    <li ng-class="{active:isActive == '/test1'}">
                        <a href="#/test1">Test1</a>
                    </li>
                    <li ng-class="{active:isActive == '/test2'}">
                        <a href="#/test2">Test2</a>
                    </li>
                </ul>
            </div>
        </div>
    </div>
    <div class="container body-content">
        <div ng-view></div>
    </div>

    @Scripts.Render("~/bundles/angular")
    @Scripts.Render("~/bundles/app")
</body>

HomeController (ASP.NET):

namespace Tests.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return PartialView();
        }

        public ActionResult Test1()
        {
            return PartialView();
        }

        public ActionResult Test2()
        {
            return PartialView();
        }
    }
}

My Angular module:

angular
   .module('Tests', [
      'ngRoute'
   ])
   .config(config)
   .run(['$rootScope', '$route', '$location', function($rootScope, $route, $location) {
      $rootScope.$on('$routeChangeSuccess', function(event, currRoute, prevRoute) {
         $rootScope.title = $route.current.title;
      });

      var path = function() {
         return $location.path();
      };

      $rootScope.$watch(path, function(newPath, oldPath) {
         $rootScope.isActive = newPath;
      });
   }]);

config.$inject = ['$routeProvider'];

function config($routeProvider) {
   $routeProvider
      .when('/test1', {
         templateUrl: '/Home/Test1',
         isActive: 'test1'
      })
      .when('/test2', {
         templateUrl: '/Home/Test2',
         isActive: 'test2'
      })
      .otherwise({
         redirectTo: '/'
      });
}

The output URL is shown as follows: localhost/Home/Index#/test1

Question:

Do I need to define Actions in HomeController and why? I thought I need just the ActionResult Index because I use PartialView()... And how can I achieve the following URL: localhost/test1 when I click on the Menu Test1?

解决方案

In addition to what @Andiih stated in his answer. The Angular routing library is meant to handle your Angular routes E.G. between front end controllers.

You seem to have mixed Angular and ASP.NET MVC routing in the way you're expecting the 2 to work. Your base route is localhost/Home/Index# from that point onward Angular appends its own (sub) routes to the base URL, resulting in the output URL that you're seeing.

Even though it might be feasible jumping between MVC and Angular routes and controllers as needed, it would be a more complicated scenario than what I'm assuming you're aiming to achieve. Also I've never needed to go to that extent in the past.

In summary what would currently happen:

If you had to navigate away from your Index.cshtml "Root" page you'd in effect navigate away from your current Angular app.. or navigate to a different app... depending on solution structure you could even use different JavaScript MV* framework for each a separate page... but that's just madness.

...but I doubt it is what you want at this stage, so for simplicity sake lets stick to assuming you only have the one ASP.Net MVC Route / Page, and you just purely want to navigate between Angular routes and supply data to the Angular routes or pages from your back end .NET services somehow.

Thus it seems that you could potentially be missing a link between what roles each of the frameworks are meant to play in the stack you currently have. (I'll try clarify)

For example:

If you look at a (very generic) overall solution structure that could look something like this below.

    - css
       - bootstrap.css        // all 3rd party css here
    - libs
       - angular.js           // all 3rd party js libs here
       - angular-ui-router.js
    - controllers
       - RootController.cs    // This is your HomeController.
                              // It's effectively used to "deliver" the root view which is
                              // your core/base page for lack of a better term
    - views
       - RootView.cshtml      // see code RootView.cshtml below,
                              // this defines your app "layout"
                              // as well as where you deliver your bundles,
                              // make use of server side auth, etc..
    - webapi
       - test1Api.cs          // access to test1 data or serverside process
       - test2Api.cs          // etc..
    - app
      - pages
          - home
          - test1
             - test1Ctrl.js
             - test1View.html
             - test1.css
          - test2
             - test2Ctrl.js
             - test2View.html
             - test2.css
      - services
         - someRandomSvc.js
         - resourceSvc.js   // this is where you consume your
                            // .NET back end API. E.G: test1Api & test2Api, etc..
      - app.js
      - app.routes.js
      - etc...

The RootView.cshtml gets constructed server-side, thus allowing you to use .NET bundling, Asp.NET Auth etc.. Anyhow, this whole page will act as a shell for the Angular app, the whole "front end app", thus runs within the context of that page.

RootView.cshtml

<head>
    @Styles.Render("~/content/3rdPartyCSS")
    @Styles.Render("~/content/appSpecificCSS")
</head>
<body>
    <div class="navbar navbar-default navbar-fixed-top">
    <div class="container">
        <div class="navbar-collapse collapse glyphicons pull-right">
            <ul class="nav navbar-nav">
                <li><a ui-sref="home">Home</a></li>
                <li><a ui-sref="test1">Test1</a></li>
                <li><a ui-sref="test2">Test2</a></li>
            </ul>
        </div>
    </div>
    </div>
    <div class="container body-content">
        <div ng-view></div>
    </div>

    @Scripts.Render("~/bundles/3rdPartyJS")
    @Scripts.Render("~/bundles/appSpecificJS")
</body>

You'll only need a single ASP.Net MVC Route, as I've stated before, you won't be navigating away from it (for this app at-least)

RootController.cs

namespace Tests.Controllers
{
    public class RootController : Controller
    {
        public ActionResult RootView()
        {
            // as I've mentioned previously in another post,
            // we're returning a partial to avoid the usage of _layout.cshtml
            // as our RootView is acting as the layout in for the angular app.
            // (it would introduce another level of not needed nesting)
            return PartialView();
        }
    }
}

... but you will need multiple Angular routes.

app.routes.js

var app = angular.module('Tests');
app.config(['$stateprovider', function($stateprovider) {
  $stateprovider
     .state('home', { url: '', templateUrl: 'app/pages/home/homeView.html' }])
     .state('test1', { url: '/test1', templateUrl: 'app/pages/test1/test1View.html'})
     .state('test2', { url: '/test2', templateUrl: 'app/pages/test2/test2View.html'});
}]);

You would then expose the other server-side logic or calls via WebAPI endpoints that you would need to consume via something like ngResource, which you will then utilize in your Angular controllers.

testXView.html

<div ng-controller="testXCtrl as test">{{ test.something }}</div>

testXCtrl.js

var app = angular.module('Test');
app.controller('testXCtrl',['resourceSvc', function(resourceSvc) {
   resourceSvc.getSomeData().then(function(data) {
       this.something = data;  //.. or whatever floats your boat :P
   })
}]);

Note.

  1. Using this convention with angular .something(['service', function(service) { }]); is to make the code min safe. (So don't be too scared when you see it)
  2. I used a routing library called angular-ui-router in my example, I suggest that you have a look at it, if you have the freedom to choose at this stage... but the same principals would apply to an ngRoute solution.

这篇关于如何在 ASP.NET MVC 中定义 Angular Routing的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-25 23:34