Click here to Skip to main content
15,886,258 members
Articles / Programming Languages / C# 5.0
Tip/Trick

Angular JS and ASP.NET, All those Script Files

Rate me:
Please Sign up or sign in to vote.
4.97/5 (12 votes)
15 Oct 2014CPOL2 min read 20.7K   27   6
My way of diminishing the need to write out all those angular script files

Introduction

So I've recently ramped up my interaction with Angular JS. One of the first things that I thought had to be improved and made much much easier was how the scripts get added to your index page.

This is totally dependent on your approach to Angular JS, and currently with my approach, this is a solution to a problem that occurred for me.

I tackle Angular JS using the conventions set out in the Angular Seed App.

Angular Construction

File Structure

So, I separate out my files for each "area", one file for area.controllers.js, one file for area.services.js so I build up a file structure like so:

  • Angular\
    • Account\
      • account.controllers.js
      • account.services.js
    • Blog\
      • blog.controllers.js
      • blog.services.js
    • App.js

So with this method of naming conventions and separations, it makes it incredibly easy to find a particular place in my app. If I got an error, I can be like "that happened in my account page, let's get to Account -> account.controllers.js" and there is no need to scan one file for the line that specified .controllers('accountController', function ()).

Code Structure

In my files, I like to carry on the naming convention:

JavaScript
angular.module('account.controllers', [])  
.controllers('accountController', ['$scope', function ( $scope ) {

}]);

There are also other conventions I would like to point out, I use the dependency injection that Angular provides, apparently this helps .NET with minification. Also I use the [] in the module parameter, this instantiates a new module and in my mind a new scope.

So now you've seen [] you may ask how do you then use services that you create, etc.

Answer: I instantiate my Angular app like so:

JavaScript
angular.module('myApp', [  
    'ngRoute',
    'ngResources',
    'account.services',
    'account.controllers'
]); // usually I put the routing on here as well

This way, all the dependencies get loaded up and everything works.

ASP.NET Problem

The BundleConfig.cs is the big problem here. This is the code:

C#
public class BundleConfig  
{
    // For more information on bundling, visit http://go.microsoft.com/fwlink/?LinkId=301862
    public static void RegisterBundles(BundleCollection bundles)
    {
        bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                    "~/Scripts/jquery-{version}.js"));

        bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
                    "~/Scripts/jquery.validate*"));

        // Use the development version of Modernizr to develop with and learn from. Then, when you're
        // ready for production, use the build tool at http://modernizr.com to pick only the tests you need.
        bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
                    "~/Scripts/modernizr-*"));

        bundles.Add(new StyleBundle("~/bundles/main/css").Include(
                    "~/Content/site.css",
                    "~/Content/font-awesome.css"));

        // LIST ALL ANGULAR FILES HERE
    }
}

Okay, so not the biggest problem in the world, you just create the bundle and add all the files to it.

C#
bundles.Add(new ScriptBundle("~/bundles/angularapp").Include(  
                "~/Angular/Account/account.controllers.js"));

Even the small example here was a bit laborious to type out. This could easily be prone to mis-types.

One solution I have is this:

C#
// BundleBuilder.cs
public static class BundleBuilder  
{
    public static Bundle Build(string bundleName, KeyValuePair<string, string[]>[] angularDictionary)
    {
        var virtualPaths = new List<string>();

        foreach (var reference in angularDictionary)
        {
            foreach (var file in reference.Value)
            {
                var bundle = new StringBuilder();
                bundle.Append("~/Angular/");
                bundle.Append(reference.Key);
                bundle.Append("/");
                bundle.Append(reference.Key.ToLower());
                bundle.Append(".");
                bundle.Append(file);
                bundle.Append(".js");

                virtualPaths.Add(bundle.ToString());
            }
        }

        var bundlePath = new StringBuilder();
        bundlePath.Append("~/bundles/");
        bundlePath.Append(bundleName.ToLower());

        return new ScriptBundle(bundlePath.ToString()).Include(virtualPaths.ToArray());
    }
}

// for the account bundles do this:
public static class AccountBundle  
{
    public static KeyValuePair<string, string[]> Scripts()
    {
        return new KeyValuePair<string, string[]>("Account", new[] { "controllers", "filter" });
    }
}

So now the BundleConfig.cs will look like this:

C#
// FROM
bundles.Add(new ScriptBundle("~/bundles/angularapp").Include(  
                "~/Angular/Account/account.controllers.js"));

// TO 
bundles.Add(  
    BundleBuilder.Build(
        bundleName: "angularapp", 
        angularDictionary: new[]
            {
                AccountBundle.Scripts()
                // so on so fourth
            }));

Points of Interest

  1. Code Readability
  2. Repetition

This way is very readable, you know there is an AccountBundle for example and you know it generates the paths for the Scripts.

There are standards that you define when creating virtual paths and very little repitition. This minimises human error when writing the path out. Less of that "why isn't the whole functionality working, why hasn't the script been included, oh I missed a dot".

So now in the Razor view, we add this line:

ASP.NET
<!-- Index.cshtml -->

@Scripts.Render("~/bundles/angularapp");

Conclusion

So all in all, a pretty neat solution, I'm not saying it's the best, or the most optimised, just something I whipped up on the fly.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
United Kingdom United Kingdom
I've just started out on my career path. I use .NET technologies and JavaScript.

Comments and Discussions

 
Questiongreat read Pin
rammanusani26-Mar-19 8:12
rammanusani26-Mar-19 8:12 
SuggestionPlease, append more info! Pin
Carlos190716-Oct-14 0:11
professionalCarlos190716-Oct-14 0:11 
GeneralRe: Please, append more info! Pin
Callum Linington (UK)16-Oct-14 0:48
Callum Linington (UK)16-Oct-14 0:48 
Questionthe bundling supports * Pin
Sacha Barber15-Oct-14 20:13
Sacha Barber15-Oct-14 20:13 
AnswerRe: the bundling supports * Pin
Callum Linington (UK)15-Oct-14 23:50
Callum Linington (UK)15-Oct-14 23:50 
GeneralRe: the bundling supports * Pin
Sacha Barber17-Oct-14 3:25
Sacha Barber17-Oct-14 3:25 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.