How to use ASP.NET MVC and AngularJS routing?

lmttag picture lmttag · May 15, 2014 · Viewed 56.8k times · Source

I’m working on a new ASP.NET MVC and AngularJS application that is intended to be a collection of SPAs. I’m using the MVC areas concept to separate each individual SPA, and then I’m using AngularJS within each MVC area to create the SPA.

Since I’m new to AngularJS and haven’t been able to find an answer regarding combining both MVC and AngularJS routing, I thought I’d post my question here to see if I could get some help.

I have the standard MVC routing setup, which serves up each MVC area.

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.MapMvcAttributeRoutes();
        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
        routes.AppendTrailingSlash = true;
    }

This works fine and gives me URLs like:

http://servername/Application1/
http://servername/Application2/

Now, within each application area, I’m trying to use AngularJS routing, also using $locationProvider.html5Mode(true); so that I get the client-side routing within each area, something like:

http://servername/Application1/view1
http://servername/Application1/view2
http://servername/Application2/view1/view1a
http://servername/Application2/view2/view2a
http://servername/Application2/view3

Here’s my AngularJS routing snippet for Application1:

app1.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
    var viewBase = '/Areas/Application1/app/views/';
    $routeProvider
        .when('/Application1/view1', {
            controller: 'View1Controller',
            templateUrl: viewBase + 'view1.html'
        })
        .when('/Application2/view2', {
            controller: 'View2Controller',
            templateUrl: viewBase + 'view2.html'
        })
        .otherwise({ redirectTo: '/Application1/view1' });
    $locationProvider.html5Mode(true);
}]);

So, initially, it seems to work (at least the URL looks correct). But, when I start navigating between areas or views within an area, or even if I refresh, something gets “lost” and things don’t work. The URL still looks correct but views aren’t found and aren’t getting loaded correctly.

Any help/guidance on how to make ASP.NET MVC and AngularJS routing work together to give me the scenario described above?

Thanks!!!

Answer

lmttag picture lmttag · Jun 6, 2014

Thanks for the answer, agbenyezi. I looked at the article you provided but it only got me back to where I was anyway.

However, I was able to figure it out and get it working. The answer turned out to be relatively simple, but it took some time and a lot of searching around. Anyway, since I am using MVC areas, navigating to a URL of http://servername/Application1/view[x] (where Application1 is the MVC controller (in the area) and view1, view2, view3, etc. are Angularjs views), the MVC part of the overall application was getting confused and trying to find an action named view[x] in the Application1 controller (which doesn't exist).

So, in the area's AreaRegistration class (where it's defining specific routes for the area), I just needed to add a kind of catch-all route before any default MVC routes to always force it to the Index action on the Application controller. Something like:

        // Route override to work with Angularjs and HTML5 routing
        context.MapRoute(
            name: "Application1Override",
            url: "Application1/{*.}",
            defaults: new { controller = "Application1", action = "Index" }
        );

Now, when I navigate to http://servername/Application1/view[x] it routes to the Application1 MVC controller, Index action, and then Angularjs takes over routes to the different views, all while having the HTML5 routing construct in the URL.

Hope that helps others.

Thanks!