JSPM with SystemJS, ES6, AngularJS, TypeScript and ASP.NET Core – Part 4 [Integration]

  • April 12, 2016
  • WebDev

Note: in this series I’m using some UNIX commands like touch and mkdir. If you’re using Windows, those commands can be ran if you’re using cmder, the appropriate related command for Windows or creating files and folders using the GUI.


Prerequisites

In the first three parts of this series we learned how to setup and create the frontend and the backend project. Now we’re going to integrate both and simulate a real world application.

Remember again this tutorial is targeted to UNIX users (more specifically MacOS), if you’re using Windows be sure to adjust accordingly where I haven’t done so already. Or you could achieve similar results by using cmder on Windows, I highly recommend using it!


Part 4 – Integrating the backend with the frontend

Ok! So now we start part 4! Integration, integration! Let’s see how we can integrate both projects (frontend and backend).

This part is long so I’m just going to post the code and then explain everything at the bottom

The first thing we’re going to do is create a folder named app.server right under src, then create a file named index.ts there. Then, create a new folder under app.server named user and inside that folder 4 new files: user.html, user.ts, user-component.ts and user-controller.ts. Our new structure is going to look like this:

Open the terminal and run the command jspm install npm:angular-resource.

Now let’s insert the following code in our user.html:

[code lang=”html”]
<div class="media">
<div class="media-left">
<a href="#">
<img class="media-object" src="{{$ctrl.user.ImageUrl}}">
</a>
</div>
<div class="media-body">
<h4 class="media-heading">{{$ctrl.user.Name}}</h4>
{{$ctrl.user.Content}}
</div>
</div>
[/code]

The following one on our user.ts:

[code lang=”js”]
export interface User {
Name: string;
Content: string;
ImageUrl: string;
}
[/code]

The following one on our user-controller.ts:

[code lang=”js”]
‘use strict’;

import {User} from ‘./user’;

interface IUserController {
user: User;
loadUser(): void;
}

export default class UserController implements IUserController {
public user: User;
public localResource: ng.resource.IResourceService;

static $inject = [
"$resource"
];

constructor($resource: ng.resource.IResourceService) {
this.localResource = $resource;
this.loadUser();
}

loadUser(): void {
var curController: UserController = this;

this.localResource<User>(‘http://localhost:5000/api/users/1’, {
‘get’: { method: ‘GET’ }
}).get().$promise.then(function(response: User) {
curController.user = response;
});
}
}
[/code]

And the following one on our user-component.ts:

[code lang=”js”]
‘use strict’;

import UserController from ‘./user-controller’;

export default class UserComponent implements ng.IComponentOptions {
public controller: any;
public templateUrl: string;
public bindings: any;

constructor() {
this.bindings = {};
this.controller = UserController;
this.templateUrl = ‘/src/app.server/user/user.html’;
}
}
[/code]

Then we’re going to change our index.ts under app.server file to look like this:

[code lang=”js”]
‘use strict’;

import ‘angular’;
import ‘angular-resource’;
import UserController from ‘./user/user-controller’;
import UserComponent from ‘./user/user-component’;

export default angular.module(‘app.server’, [
‘ngResource’
])
.controller(‘UserController’, UserController)
.component(‘userComponent’, new UserComponent());
[/code]

Now we’re going to change our index.ts under app file to look like this:

[code lang=”js”]
‘use strict’;

import appServer from ‘../app.server/index’;

export default angular.module(‘app’, [
appServer.name
]);

angular.bootstrap(document.documentElement, [‘app’]);
[/code]

Finally, we change the index.html file to:

[code lang=”html”]
<!DOCTYPE html>
<meta charset="utf-8">
<script src="jspm_packages/system.js"></script>
<script src="jspm.browser.js"></script>
<script src="jspm.config.js"></script>

<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />

<body>
<div id="container">
<h1><span class="label label-warning">Ahoy!</span></h1>
<user-component></user-component>
</div>

<script>
SystemJS.import(‘src/app’);
</script>
</body>
[/code]

If you’re using Google Chrome and receive this error:

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.

You’ll have to run Google Chrome with the flag <span class="s1">--disable-web-security</span>. On MacOS the code would be:

<span class="s1">/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --disable-web-security --user-data-dir=~/ChromeUserData/</span>

Now let’s move to the backend project! Open the project and create a new folder called Models and inside that folder a new file named User.cs. That file will look like:

[code lang=”csharp”]
namespace BlackBeard.Controllers
{
public class User
{
public string Name { get; set; }
public string Content { get; set; }
public string ImageUrl { get; set; }
}
}
[/code]

Then create a new file under the folder Controllers. Let’s call it UserController.cs and fill it with:

[code lang=”csharp”]
using System.Collections.Generic;
using Microsoft.AspNet.Mvc;

namespace BlackBeard.Controllers
{
[Route("api/[controller]")]
public class UsersController : Controller
{
User[] users = new User[] {
new User {
Name = "William Kidd",
Content = "(Scottish, 1645 – 1701)",
ImageUrl = "http://historylists.org/images/william-kidd.jpg"
},
new User {
Name = "Edward Teach \"Blackbeard\"",
Content = "(English, 1680- 1718)",
ImageUrl = "http://historylists.org/images/edward-teach.jpg"
}};

// GET: api/users
[HttpGet]
public IEnumerable<User> Get()
{
return users;
}

// GET api/users/5
[HttpGet("{id}")]
public User Get(int id)
{
return users[id];
}

// POST api/users
[HttpPost]
public void Post([FromBody]User value)
{
}

// PUT api/users/
[HttpPut("{id}")]
public void Put(int id, [FromBody]User value)
{
}

// DELETE api/users/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
}
[/code]

Now you can run the frontend (http-server) and the backend (dnx web) again. If everything was done correctly you should see the following result:

Now a little bit of explanation…

First of all, some things should’ve been placed in different locations. For instance, the user.ts file should’ve been placed on a different folder maybe named app.data or app.dao. The code to retrieve the resource should’ve been placed on a specific class in a different folder as well and so on. But those things are for you to fix when you create your own real world app.

Ok! So on our user.html we have pretty basic html and angular code, so I’m not going to delve deeper on that. Suffice to say that we’re accessing the controller’s variable user and then its properties:

{{$ctrl.user.ImageUrl}}

On user.ts we’re following TypeScript‘s standards and creating an interface to represent our data and typing it accordinly.

On user-controller.ts:

  1. We import the User interface
  2. Create an interface (protocol) for our controller
  3. Create the controller class implementing the interface
  4. Make use of the `static $inject` to inject dependencies on `TypeScript` code
  5. Make a request to our WebApi project using `angular`’s `$promise`

On user-component.ts we create an angular component using user.html as our template.

On app.server/index.ts:

  1. We import the needed libraries and the locally created Controller and Component
  2. Define our module, it’s dependencies and the controller and component

On app/index.ts we just define our module, import the server module and bootstrap the application.

And that’s it for part 4! Now we have a fully operational frontend and backend project communicating with each other. The goal was to stop here, but I’m going to add a fifth part to this tutorial explaining how to use a database and maybe a sixth explaining how to deploy both projects.

Both projects have been updated on GitHub!

 

RedBeard on GitHub

BlackBeard on GitHub

Stay tuned!




No Comments


You can leave the first : )



Leave a Reply

Your email address will not be published. Required fields are marked *