Okay, this seems to be getting the better of me.
I've been reading blog after blog, where guys explain how to get this going, but after countless hours of removing, adding, changing, debugging, pulling-at-hair, copious amounts of coffee and no luck in getting this to work, I'm turning here for some professional insight.
As the title suggest, I'm trying to get angular to work within an MVC 5 with Razor views, but I'm experiencing some very weird behavior.
Firstly, angular does not kick in on page load. I have to refresh the landing page at least 5 - 10 times before it kicks in.
When it eventually works, Chrome goes into overburn, consuming nearly all of the available resources before crashing. Console in developer tools comes up with a message "Warning: Trying to load angular multiple times".
The error is very descriptive, so I assume that I'm loading the _layout.cshtml page twice, when the client-side routing eventually kicks in, but each Razor view contains the @{ Layout = null } call, as it has been explained on so many blogs.
I've tried everything I could possibly read up on, and I cannot get passed this issue.
Following, my code:
ASP.Net Razor View
1.) _Layout.cshtml
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" data-ng-app="webStudio" data-ng-controller="StudioController"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width" /> <title data-ng-bind="Page.title">...</title> <base href="/" /> @Styles.Render("~/Content/css") @Scripts.Render("~/bundles/modernizr") </head> <body> <div class="page {{css}}" data-ng-view=""> @RenderBody() </div> <div class="__javascript-webstudio"> @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/ng") @Scripts.Render("~/bundles/yeti") @Scripts.Render("~/bundles/ngapp") @Scripts.Render("~/bundles/ngfactory") @Scripts.Render("~/bundles/ngservice") @Scripts.Render("~/bundles/ngcontroller") @RenderSection("scripts", required: false) </div> </body> </html>
I assumed that, because the _layout.cshtml
is used for the index page (Home), it is where the angular instantiate should occur. I've seen blogs where they skip the _layout.cshtml
all together, but to keep it consistent, I want this to be my starting point. I have tried to not use Layout in Home/Index, and call all my scripts in there, but it does the exact same thing, couple of refreshes, and Warning.
2.) Home/Index.cshtml
@*{ Layout = null }*@ <a href="@Url.Action("Index", "Gallery")">Go there</a>
Layout = null
has been commented out, because this causes _layout.cshtml
to not even load my JS files, weird behaviour :/
3.) Gallery/Index.cshtml
@{ Layout = null; } Date: @DateTime.Now
This is just a page to test the route.
4.) Web.config
<rewrite> <rules> <rule name="AngularJS" stopProcessing="true"> <match url=".*" /> <conditions logicalGrouping="MatchAll"> <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /> <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" /> <add input="{REQUEST_URI}" pattern="^/(api)" negate="true" /> </conditions> <action type="Rewrite" url="/" /> </rule> </rules> </rewrite>
The rewrite rule is important to ensure that the routing is done appropriately. I am using HTMLMode for angular, so this step is vital.
5.) app.js
var webStudio = angular.module("webStudio", ["ngRoute"]); webStudio.config(function ($routeProvider, $locationProvider) { $routeProvider .when("", { templateUrl: "/Home", controller: "HomeController" }) .when("/", { templateUrl: "/Home", controller: "HomeController" }) .when("/Home", { templateUrl: "/Home", controller: "HomeController" }) .otherwise({ redirectTo: "/Error/NotFound" }); $locationProvider.html5Mode(true); });
There really is nothing weird about this, it creates the angular app reference, attaches the routing to the module and form there I configure the routing behavior.
From what I've read and understand, it makes sense to call the controller/action block as you would do normally in ASP.Net MVC.
The default routing for MVC I did not touch, as it's irrelevant in this scope.
I'm at a loss as to why this behavior is occurring and don't know where to start investigating. I've read blogs on the refresh issue and have tried what has been stated, but in this scenario, I just cannot get it to work.
Update
6.) BundleConfig.cs
public static void RegisterBundles(BundleCollection bundles) { bundles.Add(new ScriptBundle("~/bundles/jquery") .Include("~/Scripts/vendor/jquery/jquery-{version}.js") .Include("~/Scripts/vendor/jquery/jquery.validate.js")); bundles.Add(new ScriptBundle("~/bundles/ng") .Include("~/Scripts/vendor/angularjs/angular.js") .Include("~/Scripts/vendor/angularjs/angular-route.js")); bundles.Add(new ScriptBundle("~/bundles/yeti") .Include("~/Scripts/vendor/ngfoundation/mm-foundation-0.6.0.js")); bundles.Add(new ScriptBundle("~/bundles/ngapp") .Include("~/Scripts/app.js")); bundles.Add(new ScriptBundle("~/bundles/ngfactory") .Include("~/Scripts/factories/studio.js")); bundles.Add(new ScriptBundle("~/bundles/ngservice") .Include("~/Scripts/services/studio.js")); bundles.Add(new ScriptBundle("~/bundles/ngcontroller") .Include("~/Scripts/controllers/studio.js")); bundles.Add(new ScriptBundle("~/bundles/modernizr") .Include("~/Scripts/vendor/modernizr-*")); bundles.Add(new StyleBundle("~/Content/css") .Include("~/Content/normalize.css") .Include("~/Content/foundation.css") .Include("~/Content/site.css")); }
BundleConfig.js
look like?