This article provides simple steps for creating a template for ASP.Net application using AngularJS, RequireJS and Typescript using AMD module system.

Introduction

This is an article about the fullstack development of an application which allows sharing of resources. By resources what I mean is files of most mime types available and articles or opinions to share. Uses various client and server development tools and techniques including Typescript, RequireJS, AMD, AngularJS and several others too.

Background

This article was the result of my search for a similar technical content but no avail. My sincere hope is that at the end of this article you will be able to combine a minimum of AngularJS,Typescript and RequireJS to have a working template. The application part of this article is developed using Visual Studio 2015 Community Edition.

Most of the coding practices in this article assumes you have a comfortable command over Visual Studio and have developed ASP.Net MVC projects, WebAPI and Entity Framework before. The reason is to focus more on the AngularJS, RequireJS and Typescript development and not going to the details of ASP.Net and WebAPI or SQL coding.

Steps for Developing the Template

The article is divided into steps describing units of work. Each step contains explanation of Visual Studio use along with pictures and if any code that is relevant to that part in the step. Sometimes code may be given as part of the pictures and you need to look at the picture to edit the code yourself. You will see more pictures that gives you ideas of what to do than reading a lot.

This article is not about Object Oriented Design, Database normalizations, or how to do effective modularizing of your client code into modules and naming them.

The goal of this article is to provide a working prototype of mainly three client side frameworks/language/libraries. They are Typescript, AngularJS and RequireJS. All others are introduced as a means of achieving the goal.

Here is a list of tools, languages , packages and the version in use for the underlying application.

Visual Studio 2015 Community Edition.

.Net 4.6.1

Microsoft ASP.Net MVC 5

Microsoft ASP.Net WebAPI 2.1

AngularJS 1.4.9

Twitter bootstrap 3.0.0

RequireJS 2.1.22

TypeScript 1.7

Angularjs.TypeScript.DefinitelyTyped 5.2.1

Nuget Package Manager

EntityFramework 6.1.3

Angular.UI.Bootstrap 1.1.1

C#

Microsoft SQLServer

Eventhough the list is long, some of these items are very easy to use with the help of Visual Studio template and code generators.

Step 1

The goal of this step is to have a single page web application (SPA). If any tools or packages required are missing, you might need to add them to your Visual Studio Edition before the end of this step. At the end of this step, you can exceute or debug the project to show a web page in your browser without any content in it.

Open Visual Studio and start a new ASP.Net Web Application project. You may name the project of your choice. As you can see, I am using .Net Framework 4.6.1. There is not much of a hard dependency on the version as it might work for lower versions. I haven't tested that though.

I am selecting an empty template with support for WebApi. This project uses MVC framework only for namesake and I will show you, how Visual Studio automatically add suport for MVC later during development.

Now we are done with the project creation and the below picture shows the resulting folder structure of the project.

Next I am adding a local SQLServer Database to the project. Right click on the project in the solution explorer and navigate through the menu to add a new item. Select Data on the installed templates on the left side and choose SQLServer Database. Give a name of your choice. Click "Add" button to add the database.

The wizard will ask the location of the database file and accept App_Data as the location since it provides ASP.Net default security for the folder.

The Database created above is not used until Step 3. The reason for including it here is to have a basic Web Application ready by the end of this step.

Next is to add an MVC empty controller. Keep in mind that we did not add any support for MVC while creating the project. So during this controller addition, Visual Studio must add the necessary folders, references, and files to the project. The controller only works as a means of opening the default view and don't include any read/write actions or using the Entity Framework to do any database operations.

The controller is named as LoginController. The name is important and if you name it anything else, the RouteConfig file need to be edited accordingly below.

You can click "Add" and unless there are no issues with the Visual Studio setup, you should get the controller added. There could be scenarios where you may get some error related to MVC framework support addition.

(In that error scenario, it will be possible to circumvent the visual studio process and manually add the folders, edit the web.config file inside the view folder and create and add the view before adding the controller. If any such thing happens, you may add some comments, and I can provide alternate steps to overcome the problems. Another step is to start from scratch again and create a brand new project and repeat the steps.)

Once the MVC controller is added, you can see the resulting folder structure as below. There are some files and folders not required for the AngularJS,Typescript and RequireJS template and we can remove them in the next substeps.

The "Shared" folder, the layout and error html files are not needed since this is a SPA (single page application).

Some of the javascript files inside Scripts folder are also not required and they can be removed later when you deal with the Nuget package manager.

When the controller is added, a readme file is opened in the source editor window. The steps in that file are followed to get default routing is working for both MVC and WebApi. The WebApi config registration must be before the MVC routing support is added.

We don't need to bundle any javascript or css files as we are dependent on RequireJS to load the modules we needed and also use Typescripts importing of modules as and when required. We also use AngularJS directives in the last step to pull some html templates which is provided free as part of the AngularJS-UI-Bootstrap package. If you want to see the downloading of the files in action use the Development tools by clicking F12 and see them while the pages are loading.

Next delete the BundleConfig.cs file from the "App_Start" folder.

Delete the ViewStart.cshtml next.

The RouteConfig.cs file is edited to have the default controller set. If you don't set this, the application won't be able to route the traffic to the correct controller and may end up in an error page.

Right click on the "Login" folder and add an HTML page. Name the page as Index.cshtml. Since this is an MVC project, the extension expected is cshtml, but the content of this file will not have any Razor syntax in it.

We modify the content of the head as follows. The body will be added in Step 2 of this article.

Step 2

This step starts with adding the required Nuget packages for Angular, RequireJS, DefintelyTyped for Angular, Typescript support and bootstrap.

Right click on the project in Solution Explorer and open the Nuget Package Manager window. We need to search for the packages and for making it easier, do not open the console and install using the command prompt. If you know the package names and versions in advance, you are free to follow that path. I will post the content of the packges.config later at the end of this step so that advanced users may use the console instead.

Next we are installing the Typescript definitions for RequireJS. A typescript project looks for definitions as classes and not as traditional javascript functions. The type-definition files provide these definitions. Download and install requirejs.TypeScript.DefinitelyTyped package v0.2.9 now.

Once the package is installed, a new dialog will come up asking for adding the support for typescript in your project. You need to answer "Yes" for this dialog so that all typescript typings for all the javascript libraries included are installed by the package manager.

Next add the AngularJS core package. We don't need to add all of the AngularJS modules but only selective ones like core, routing and sanitize which is enough for this project.

Next download and install the routing module.

Download and install Sanitize which is required as part of some advance Angular support later in the steps.

It is time to add the typescript definitions for the angular packages now.

We are adding some AngularUI components like Accordian and Collapse later in the last step. Add the AngularUI Bootstrap package.

Next two are very important parts and without it, the project will not build and I could see a lot of searches in Google for how to solve these build errors. The errors are because of the version that is installed as default and the update is a must. Type jquery in the browse tab of Nuget package manager and install the typescript definitely typed for jquery. Angular uses these jquery definitions.

Update the installed jquery version to the stable 2.2.0.

As promised in the beginning of this step, the package.config file image is as below. Some of the existing packages like modernizer are removed.

It is time to add some typescript code to the project.

Right click on the "Scripts" folder in Solution Explorer and add a new folder named "appScripts" now. All the typescript code for the angular controllers, services and routing will reside here. I could have added separate folders for controllers and other artifacts but as I said in the beginning of this article, what we need is just a prototype and folder structure is not a goal.

Right click on "Scripts" folder and add a new typescript file as shown below. Let the name of the file be main.ts.

Drag and drop "angular.d.ts" and "angular-route.d.ts" from inside the typings/angularjs folder to the main.ts file opened in the source editor as below.

Add a new typescript file "mainControllers.ts" inside "appScripts" folder. This is to define the collection of controllers that will be used in the application. In this step there will be only a single controller called MainController and its responsibility is trivial like adding a couple of variables to the $scope. (The code is formatted as javascript since no typescript formatting is available.)

This typescript file exports a class called mainControllers to any other typescript file which can import this class and instantiate it to create a new object of its type and invoke publicly exposed methods in it. Inside the constructor of this class, a new angular module named "mainControllers" is created. This module has a single controller "MainController" which will be used to inject the scope and populate the scopes variables to be used in the view.

As mentioned before we use RequireJS to specify the module and call it "mainCtrlsModule". We instantiate the mainControllers class from it. The application module that we are using is "shareApp" and we are injecting "ngRoute", "ngSanitize", "ui.bootstrap" and "mainControllers" to the ngApp module we created. The picture gets more clear when we modify the main.ts to include more code in it. Here is the code to be added to the main.ts file.

The content added now to the main.ts file does the RequireJS module definition and dependancy management.

In the config call, the base folder where the code for the application resides is specified. The paths below lists all the code paths and they are relative to the baseUrl folder specified. The shim is used to mention about the dependencies of each module. For example, bootstrap is dependent on jquery. In the main page, when responsive layout is used and when the menus are collapsed, a click will expand it only when bootstrap javascript code calls the jquery code. Similarly the angular-route module is dependant on angular module.

We are creating the main requirejs object by passing the app module as argument and creating an instance of shareApp class. We don't specify ng-app in the html file. This is because, the routing will not be loaded correctly by the time the document is ready. So we do a manual bootstrap of angular only when the HTML document is ready.

In this step there is no routing involved and we might use ng-app angular directive but for preparing for Step 3, the manual bootstrap is included here.

Next part is the modification of the index.cshtml file.

Before the end of the head section, we add the following

<scriptdata-main="/Scripts/main"src="~/Scripts/require.js"></script>

This is like adding a normal javascript file reference to any html file. The data-main is the important part here. What it is saying is the RequireJS should look inside a file called main.js in "Scripts" folder to get more information about the configuration and the initialization. Even though we added "main.ts" which is a typescript file, the typescript compiler converts it to javascript file.

We will now add some menu items and default angular bindings for the trivial scope variables added. The resulting index.cshtml file will be like below.

There is a final step before building the project. Right click on the project and open properties.

Go to TypeScript Build property page and select the ECMAScript version as ECMAScript 5. Also specify the module system as AMD. This will enable the export of typescript classes and import of them.

Any build before enabling the module system might end up in build failures. So build the project only after modifying the Typescript Build properties.

Execute or debug to see the page below.

Source code for this step is provided below. It does not contain the project file or database file. They have to be created by following the steps. Some of the package vesrions are new since the original write up is done about 3 months back.

Add the reference to the css file in the main.cshtml file as shown below.

An optional icon file for the application can be added at this point. Create a folder "image" inside "Content" folder and create a file "favicon.ico". This is optional and how to create it can be found from browsing internet.

Now double-click on the mdf file inside "App_Data" folder and open the Server Explorer.

Right click on the Tables and click on the menu item "New Query" to open the SQL query editor window.

In Database development, to support the DB principles, I should have made the StudentId in the Buddy table a foreign key of the Student table. Same is true in the case of resource table too. But as I mentioned, there are no Database principles followed here and just want to get the data stored and retrieved for the sake of data.

In the Buddy table, StudentId and BuddyId are unique so that no duplication is allowed. Password is only name sake and not used for login. But some string need to be entered while logging in.

Execute the query so that we have the three tables created.

Now is the time to create the model which followes the tables created in the database. Right click on the "Models" folder and click add new item.

We are adding ADO.Net Entity Data Model and we get all the supporting code for DataContext and reading and writing the application data free from the template generator. Give a name for the model. I use ShareItModel.

Next in the wizard step is to choose the content of the model. I choose Entity Framework Designer. The edmx file is generated and the diagram of all the entities generated can be viewed.

Accept the defaults in the next wizard step as this contains the connection properties to be added in the web.config file.

In the next step, all the three tables created are selected to generate the classes for them and the supporting code to populate them and retrieve data from them.

We can end the wizard and the supporting classes are created. The edmx diagram can be closed as this is not useful and we are not changing it as part of this project.

At this pont the project need to be built. If the project is not built now, adding the WebApi controllers which uses these model classes will not succeed.

Execute or debug the project to see the CSS3 added before came to effect.

The next item is adding WebApi controller. Right click the "Controllers" folder and click on "Controller..". This is to add a new controller. The WebAPI 2 controller with actions using entity Framework is chosen.

Next is to name the controller and choose the model class and the Data context class.

Click "Add" and the resulting code is a file named StudentsController.cs inside Controllers folder. The file need to be modified to support a login api call and to censor the password data. The password is not used in this application for any authentication or authorization, but just to demonstrate it. Add a static class called "utils" and add a method. (Prolonged use of javascript is making me to do mistakes like naming a class without uppercase letter in the beginning).

The index.cshtml file content is modified to remove the trivial scope variables and to add support for the student login.

The code for the additional api call in the Students controller is below. Before the student is returned, it is censored by making the call to utils.CensorStudent.

An interface is declared with the methods to be implemented by any class which implements it. exportService is a class which keeps the injected $http and then assigns the exportService to serviceHandler so that it can be used for subsequent calls.

In Step 2, the mainControllers uses a trivial controller without any name and having a couple of scope variables. Now is the time to add a loginController.ts file in the appScripts folder.

Inside the loginController, the serviceHandler is used to do http calls like Get and Post. The $http is not injected here inside loginController, but by the time this code is executed, Angular already injects $http into serviceHandler. The code is below.

Next is to add a Router. This is a client router and the code and the html are downloaded using XmlHttpRequest. As I said before, use developer tools and see it in action during the pages are loaded when routing happens. Right click the "appScripts" and add a typescript file named configRouter.ts.

The content of the configRouter is below. There are files and controller code to be added for this to function and these are done in the remaining part of this step and in the next step.

The new files added so far need to be reflected in the paths in the RequireJS main file. See the picture below.

The partial views need to be created now. Create a folder named "PartialViews" in the root level of the project.

Add a new html file with name "Register.html" inside this folder.

The content of this html file is as follows. This content is served as the Angular ng-view content. In otherwords, this html code is inserted inside where the ng-view is specified. That is the reason this file don't follow a standard HTML5 document structure with html, body tags etc.

Now the wiring of all these controllers, service factory and router need to happen. This will be inside the mainControllers file. The anonymous controller which was doing the two scope variables addition is removed.

The configRouter class instance is created and the public method configure is injected with the $routeProvider. Based on the route, the controller is set and the html template is applied in the client and the view is rendered.

A service is created using the factory and the injected $http is set in the serviceHandler object. The two controllers for now are the loginController and registerController. The parent scope of the register controller is the loginController and is accessed to query the status of the login state.

The following pictures are for registering a new student and login in the student. The password is not used for now.

Points of Interest

There were many occassions that the project did not build or not deliver the pages correctly. Here are some of them lsited below.

The package folder location is very important if the project need to be in version control. I moved the package folder in the same level as the project file to have the references properly updated by the Nuget package manager.

Typescript module system specification is important for exporting the modules correctly.

Hi, Thanks anyway for your exensive tutorial. It seemed a promising example..., however, sorry about it, it is not working. Students get lost when you are speaking about adding two typescript files into the 'appScripts' sub folder (in the parent 'Scripts' folder) and your instruction to copy paste example two pieces of sample code to them. The shareApp.ts can NOT find the module mainControllers. I can't figure out why? Possibly, you do have a hint?
Moreover, halfway you blog you supply example code link. This example code is pretty different compared when students follow strickly your instructions.
The typescript files from your source code seems to have extra wrappers. How come? Is there a way you could repair your code and change your instruction in such a way it might work. Thanks in advance!

PS. In your example code to be added to the main.ts; in the shim: { after the first "key": ['value '] >>> missing comma <<<<<<

Sorry to hear that you have problems following the article.I will try to answer your questions, the way I understand it. If there is any disconnect, please ask more questions or attach your project file.

The shareApp.ts can NOT find the module mainControllers. I can't figure out why? Possibly, you do have a hint? => Here is the hint. The main.ts file is the solution here. The requirejs configuration makes the wiring of the modules. See "Go to TypeScript Build property page and select the ECMAScript version as ECMAScript 5. Also specify the module system as AMD" This is to be done before building the project as the project file is modified by Visual Studio so that how the typescript compiler is to be invoked.

"adding two typescript files into the 'appScripts' sub folder (in the parent 'Scripts' folder) and your instruction to copy paste example two pieces of sample code to them" => I have no clue, what you mean here.

This example code is pretty different compared when students follow strickly your instructions.The typescript files from your source code seems to have extra wrappers. How come? => This is the compiled project code and tested before adding to the article. The javascript and map files are the product of the Microsoft typescript compiler. The original article was published in January and the example code is built in March. So there are differences in the package versions.

Thanks for your reply, that's nice! However, still failures!
1) What I meant with my second question or statement: your instructions in that part of the flow are: create a sub folder named appScripts folder, put this into the Script-folder, and add into that appScripts folder two typescript files: 1) mainController.ts and 2) shareApp.ts . As soon as I add (copy paste) your sample code into that clean created shareApp.ts file I get a nice Squiggly red line telling me: cannot find module 'mainControllers'. That's the part I'm stucked. So, actually I did not reach your instructions about the property pages. So, said that

2) Your hint on first question is a part of your blog a bit later on, but anyway tweaking the typescript tab on the property page as suggested does not make any difference either.
You propably can imagine I have tried several things including building (Oké you stated: don't do that until you fishining step 2 of the instruction.

Prince, towards the instruction about adding two typescript files into that sub folder addScripts your instructions are pretty straighforward. I guess something else is missing. I have thrown everything away and started pretty punctually all over again. Exactly at the same spot... no luck. Also, if I set up your code... same thing!

PS in the shim section is missing a comma too (but I've told you already).

The red underline under "mainControllers" is expected. At this point the requirejs config and shim code is not pasted to main.ts. After pasting the code into "main.ts" and then changing the "Typescript Build" settings, the project should be able to build. At this point, look at the "shareApp.ts". The red underline would have disappeared. Please do a little "r", if not.

A little 'r' is the 'abbit', jumping out of the blackish big hat, thx!

PS
1) > Step 3) There is no main.cshtml, read Index.cshtml
2) > Pay attention to your version number of jquery (main.ts)
3) > Use *.FirstOrDefault() instead of *.First(), because when the sequence does not contain a matching element, it won't return null, instead throws an ArgumentNotFoundException right away.