Introduction
Most of the times when you are creating a .NET MVC Web Application working with AngularJS, you can find the routing is handled by both frameworks. Having said that, you also want to load the AngularJS controllers dynamically, by demand. This article shows you how to expose the AngularJS controllers in order that they can work harmoniously with MVC controllers, and they can be loaded dynamically only when they are requested.
The following image shows how angular routes the URL to be called (in this case, the MCV controller) and the Angular controller should be loaded once the client receives the response from the server for binding the view.
Following this map, we can say Angular will be routing as first step (routing administrator) and then will let MVC route to the right controller.
- Template URL: basically determines the MVC controller and action to be called
- JS Controller: JS file to be loaded for binding the view
Routing with Both MVC and AngularJS
Let’s see an example for solving the routing when implementing MVC and AngularJS 1.5.
When creating the new project, you decide to create either an empty or MVC template. In this case, we will create our project using an Empty Template. Having said that, we will need to add the ViewStart
, the Layout View and a Home Controller.
Please make sure to install AngularJS.Route
as well. This will allow you to use the Routing Modules for customizing your routes.
In the app.js, you should include the injection of ngRoute
so we can use the router provider for customizing the target controller.
In the following example, when a user types the root / it will be redirected to Home Controller and Home Action and when the server response is received, the "mycontroller
" (angular) will be loaded for binding the view.
app.js
var app = angular.module('myApp', ['ngRoute']);
app.config(['$routeProvider',
function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: '/Home/Home',
controller: 'mycontroller'
})
.when('/contact', {
templateUrl: '/Contact/Contact'
})
.otherwise({ redirectTo: '/' });
}]);
In the mycontroller.js file, we can observe we are using the module we declare in app.js for creating a new controller, which is defined in the same file.
mycontroller.js
var app = angular.module('myApp');
var mycontroller = function ($scope, $http, NgMap) {
$scope.message = "Hello World!";
};
app.controller('mycontroller', ['$scope', '$http', mycontroller]);
Include the ng-app
directive for using your Angular module. ng-view
directive is also important as we are loading the controllers and templates dynamically.
References for angular, routing and custom JS files (app and controller) should be included as well.
Layout.cshtml
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Layout</title>
</head>
<body ng-app="myApp">
<div ng-view>
@RenderBody()
</div>
<script src="~/Scripts/angularjs/angular.min.js"></script>
<script src="~/Scripts/angularjs/angular-route.min.js"></script>
<script src="~/Scripts/controllers/app.js"></script>
<script src="~/Scripts/controllers/mycontroller.js"></script>
</body>
</html>
Points of Interest
Here’s where the trick comes. As MVC framework is routing the root "/" to HomeController
(Index Action), which is returning the Index view, it is loaded and rendered by the @RenderBody
, but we are requested to load and render the Home view instead as per defined in our app.js.
Views/Home/Index.cshtml
@{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/Layout.cshtml";
}
<h2>Loading...</h2>
Views/Home/Home.cshtml
@{
Layout = null;
}
<h2>Home</h2>
<div ng-controller="mycontroller">
<span>{{ message }}</span>
</div>