How to use ASP.NET MVC and AngularJS routing?
Asked Answered
F

1

54

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!!!

Fortitude answered 15/5, 2014 at 15:10 Comment(0)
F
60

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.

Fortitude answered 5/6, 2014 at 22:34 Comment(5)
I would like to know how you organized angular JS and view code, ist it all in the scripts folder? And what do your <script tags refer to? application1/scripts/app ???Vale
What will happen if we again call action from Angular Ajax like (/Application1/Edit/2). Will it again redirect to index?Phalangeal
You are basically giving angular a path prefix. That way the templateUrl references the proper MVC route, while the url bar references the angularjs URL route option. And you put the MVC route as described above your regular MVC routes, as a catch-all. So when the /your-prefix/your/cat/52 is called, it routes to the index, which loads angularjs, and therefore loads your template using the uri. It's simply perfect. Great answer.Adala
Thanks for posting your solution! I was trying to let a single Angularjs SPA and MVC live together and this worked great for me: routes.MapRoute( name: "Default", url: "{*.}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } );Roman
I spent hours to resolve url conflicts in AngularJS+ASP.NET. This approach does not worked for me. cause i used .* (like in regex) istead of *. like here. Thanks now it works!Tape

© 2022 - 2024 — McMap. All rights reserved.