Angular MVC core ASP.NET Core
(From http://ppt.cc/47Hq0)
▌Introduction
Angular2 2.1.0
is released on October. It’s a good time to start learning it!
We can use
Angualr CLI to quickly build the architecture for ng2.
However, in
this article I will combine the frameworks and benefits of ASP.NET core MVC and
web api with Angular 2, to make a SPA (Single Page Application) sample.
▋Related articles
▋Visual Studio templates
For those who
want to quickly create the development template, there are some ASP.NET core
+angular 2 templates released.
▌Environment
▋Visual Studio 2015
Update 3
▋NPM: 3.10.3
▋Microsoft.AspNetCore.Mvc
1.0.0
▋angular 2: 2.1.0
▌Create MVC website
and install packages
▋Create MVC
Choose ASP.NET Core Web Application (.NET
Core) project template and using the EMPTY template.
▋Install frameworks/packages
Open project.json, add the following packages in
“dependencies”.
"dependencies": {
"Microsoft.NETCore.App": {
"version": "1.0.0",
"type": "platform"
},
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
"Microsoft.Extensions.Logging.Console": "1.0.0",
"Microsoft.AspNetCore.Mvc": "1.0.0",
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
"es6-shim.TypeScript.DefinitelyTyped": "0.8.1"
},
|
▋Set MVC rounting rule
We are going to set the
default and AREA routing rules for MVC.
▋Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// Add static files to the request pipeline.
app.UseStaticFiles();
app.UseMvc(routes => {
routes.MapRoute(
name: "areaRoute",
template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
|
▋View and Controller
Now we can add the controller, view and master page
(_Layout.cshtml) in the project.
Then run it!
The MVC website is ready, we will install packages for
angular2, bootstrap later.
▌Bower : install
bootstrap and jquery(optional)
▋Install
Add bower.json to the root of our project, then add the
following packages within it.
Save bower.json and wait for the packages are installed
under the path $/wwwroot/lib/.
▋Update _Layout.cshtml
Put bootstrap js and css into _Layout.cshtml’s
<header> in order to style our website.
<head>
<script src="~/lib/bootstrap/dist/js/bootstrap.min.js"></script>
<link href="~/lib/bootstrap/dist/css/bootstrap.css" rel="stylesheet" />
</head>
|
▌npm and gulp
▋Install packages
We will need the packages for developing the SPA:
Typescript
And the following packages for managing the js and
packages.
Optional js library
Here is my package.json snapshot for your reference.
{
"version": "1.0.0",
"name": "asp.net",
"private": true,
"Dependencies": {
"systemjs": "0.19.39",
"es6-shim": "^0.33.3",
"rxjs": "5.0.0-rc.1",
"sweetalert2": "5.2.1"
},
"devDependencies": {
"systemjs": "0.19.39",
"es6-shim": "^0.33.3",
"rxjs": "5.0.0-rc.1",
"gulp": "3.8.11",
"gulp-concat": "2.5.2",
"gulp-cssmin": "0.1.7",
"gulp-uglify": "1.2.0",
"rimraf": "2.2.8",
"sweetalert2": "5.2.1",
"typescript": "2.0.3",
"typings": "1.4.0"
},
"dependencies": {
"@angular/common": "^2.1.0",
"@angular/compiler": "^2.1.0",
"@angular/core": "^2.1.0",
"@angular/forms": "^2.1.0",
"@angular/http": "^2.1.0",
"@angular/platform-browser": "^2.1.0",
"@angular/platform-browser-dynamic": "^2.1.0",
"@angular/router": "3.1.0",
"reflect-metadata": "^0.1.8",
"zone.js": "^0.6.25"
}
}
|
The packages
will be installed to $/node_modules
In the next
step, we will use gulp to move the packages from $/node_modules to $/wwwroot/lib-npm
▋Gulp: tasks
Add a gulp config (gulpfile.js)
and write the copy tasks.
"use strict";
var gulp = require('gulp');
var root_path = {
webroot: "./wwwroot/"
}
//library source
root_path.nmSrc = "./node_modules/";
//library destination
root_path.package_lib = root_path.webroot + "lib-npm/"
//rxjs
gulp.task("copy-rxjs", function () {
return
gulp.src(root_path.nmSrc + '/rxjs/**/*.js', {
base:
root_path.nmSrc + '/rxjs/'
}).pipe(gulp.dest(root_path.package_lib + '/rxjs/'));
});
//reflect-metadata
gulp.task("copy-reflect-metadata", function () {
return
gulp.src(root_path.nmSrc + '/reflect-metadata/*.js', {
base:
root_path.nmSrc + '/reflect-metadata/'
}).pipe(gulp.dest(root_path.package_lib + '/reflect-metadata/'));
});
//zone.js
gulp.task("copy-zonejs", function () {
return
gulp.src(root_path.nmSrc + '/zone.js/dist/**/*.js', {
base:
root_path.nmSrc + '/zone.js/dist/'
}).pipe(gulp.dest(root_path.package_lib + '/zone.js/'));
});
//angular2
gulp.task('copy-ng2-common', function () {
return
gulp.src(root_path.nmSrc + "/@angular/common/bundles/**/*.js", {
base:
root_path.nmSrc + '/@angular/common/bundles/'
}).pipe(gulp.dest(root_path.package_lib + '/angular2/common/'));
});
gulp.task('copy-ng2-compiler', function () {
return
gulp.src(root_path.nmSrc + "/@angular/compiler/bundles/**/*.js", {
base:
root_path.nmSrc + '/@angular/compiler/bundles/'
}).pipe(gulp.dest(root_path.package_lib + '/angular2/compiler/'));
});
gulp.task('copy-ng2-core', function () {
return
gulp.src(root_path.nmSrc + "/@angular/core/bundles/**/*.js", {
base:
root_path.nmSrc + '/@angular/core/bundles/'
}).pipe(gulp.dest(root_path.package_lib + '/angular2/core/'));
});
gulp.task('copy-ng2-forms', function () {
return
gulp.src(root_path.nmSrc + "/@angular/forms/bundles/**/*.js", {
base:
root_path.nmSrc + '/@angular/forms/bundles/'
}).pipe(gulp.dest(root_path.package_lib + '/angular2/forms/'));
});
gulp.task('copy-ng2-http', function () {
return
gulp.src(root_path.nmSrc + "/@angular/http/bundles/**/*.js", {
base:
root_path.nmSrc + '/@angular/http/bundles/'
}).pipe(gulp.dest(root_path.package_lib + '/angular2/http/'));
});
gulp.task('copy-ng2-router', function () {
return
gulp.src(root_path.nmSrc + "/@angular/router/bundles/**/*.js", {
base:
root_path.nmSrc + '/@angular/router/bundles/'
}).pipe(gulp.dest(root_path.package_lib + '/angular2/router/'));
});
gulp.task('copy-ng2-platform-browser', function () {
return
gulp.src(root_path.nmSrc + "/@angular/platform-browser/bundles/**/*.js", {
base:
root_path.nmSrc + '/@angular/platform-browser/bundles/'
}).pipe(gulp.dest(root_path.package_lib + '/angular2/platform-browser/'));
});
gulp.task('copy-ng2-platform-browser-dynamic', function () {
return
gulp.src(root_path.nmSrc + "/@angular/platform-browser-dynamic/bundles/**/*.js", {
base:
root_path.nmSrc + '/@angular/platform-browser-dynamic/bundles/'
}).pipe(gulp.dest(root_path.package_lib
+ '/angular2/platform-browser-dynamic/'));
});
//systemjs
gulp.task('copy-systemjs', function () {
return
gulp.src(root_path.nmSrc + "/systemjs/dist/**/*.*", {
base:
root_path.nmSrc + '/systemjs/dist/'
}).pipe(gulp.dest(root_path.package_lib + '/systemjs'));
});
//ES6
gulp.task('copy-es6-shim', function () {
return
gulp.src(root_path.nmSrc + "/es6-shim/es6-sh*", {
base:
root_path.nmSrc + '/es6-shim/'
}).pipe(gulp.dest(root_path.package_lib + '/es6-shim'));
});
//sweetalert2
gulp.task('copy-sweetalert2', function () {
return
gulp.src(root_path.nmSrc + "/sweetalert2/dist/sweetalert2*", {
base:
root_path.nmSrc + '/sweetalert2/dist/'
}).pipe(gulp.dest(root_path.package_lib + '/sweetalert2/'));
});
gulp.task("copy-all", [
"copy-rxjs",
"copy-reflect-metadata",
"copy-zonejs",
"copy-ng2-common",
"copy-ng2-compiler",
"copy-ng2-core",
"copy-ng2-forms",
"copy-ng2-http",
"copy-ng2-router",
"copy-ng2-platform-browser",
"copy-ng2-platform-browser-dynamic",
"copy-systemjs",
"copy-es6-shim",
"copy-sweetalert2"])
|
Run the
following command (or use the task runner in visual studio).
$ gulp copy-all
|
I created an
extra folder named “typings” to store the 3rd typing definition
files.
▌Using the packages
and modules
▋Add tsconfig.json
{
"compilerOptions": {
"noImplicitAny": false,
"noEmitOnError": true,
"removeComments": false,
"sourceMap": true,
"target": "es5",
//add this to compile app component
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"module": "system",
"moduleResolution": "node"
},
"exclude": [ "node_modules", "wwwroot/lib" ]
}
|
▋Load packages
Okay, now we
can add the necessary references of the packages on the _Layout.cshtml
Notice that we
are going to use anuglar’s router for building SPA.
So we have to
set the BASE URL: <base
href="/">
<head>
<base href="/">
<script src="~/lib-npm/reflect-metadata/Reflect.js"></script>
<script src="~/lib-npm/zone.js/zone.js"></script>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib-npm/es6-shim/es6-shim.js"></script>
<script src="~/lib-npm/systemjs/system.src.js"></script>
<script src="~/lib-npm/sweetalert2/sweetalert2.min.js"></script>
<link href="~/lib-npm/sweetalert2/sweetalert2.min.css" rel="stylesheet" />
<script src="~/lib/bootstrap/dist/js/bootstrap.min.js"></script>
<link href="~/lib/bootstrap/dist/css/bootstrap.css" rel="stylesheet" />
</head>
|
▋Load dynamic modules
We are going to use Systemjs
to load the dynamic modules: @angular and rxjs.
Create systemjs.config.js in
$/wwwroot/app/ or other path.
▋systemjs.config.js
System.config({
transpiler: 'typescript',
typescriptOptions: { emitDecoratorMetadata: true },
map: {
'rxjs': 'lib-npm/rxjs',
'@angular': 'lib-npm/angular2'
},
packages: {
'rxjs': { main: 'Rx.js' },
'@angular/router': { main: 'router.umd.min.js'},
'@angular/core': { main: 'core.umd.min.js' },
'@angular/common': { main: 'common.umd.min.js' },
'@angular/compiler': { main: 'compiler.umd.min.js' },
'@angular/forms': { main: 'forms.umd.js' },
'@angular/platform-browser': { main: 'platform-browser.umd.min.js' },
'@angular/platform-browser-dynamic': { main: 'platform-browser-dynamic.umd.min.js' }
}
});
|
Next, we put
this js to the _Layout.cshtml.
<head>
<!-- skip ... -->
<script src="~/app/systemjs.config.js"></script>
</head>
|
PS. If you got any system.js error in
the following process, it may be something wrong within this file!
▌Angular2
We will create
a quick ng2 page sample in this step.
If you wanna
to know more about the basics of ng2, you can start with the official tutorial or my previous tutorial with vscode.
▋Target the browser platform, and create ng2 module and component
We need to
create the 3 files to fire an ng2 application.
1. app.module.ts : imports necessary
modules and declarations.
2. app.component.ts : our directive.
3. main.ts
: bootstrapping and target the browser platform.
▋wwwroot/app/app.component.ts
import { Component, OnInit }
from '@angular/core';
@Component({
selector: 'core-app',
template: '<h3>Hello world!</h3>'
})
export class AppComponent implements OnInit {
ngOnInit() {
}
}
|
▋wwwroot/app/app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule({
imports:
[BrowserModule],
declarations:
[AppComponent],
bootstrap:
[AppComponent]
})
export class AppModule { }
|
▋wwwroot/app/main.ts
import
{platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {AppModule} from './app.module';
import {enableProdMode} from '@angular/core';
//enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);
|
Then update
$/Views/Home/Index.cshtml and add the directive to it.
▋Views/Home/Index.cshtml
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
<core-app>
<div>
<p><img src="~/images/gif/ajax-loader.gif" /> Please wait ...</p>
</div>
</core-app>
@section Scripts {
<script>
System.config({
map: {
app: 'app'
},
packages: {
app: {main: 'main.js',defaultExtension: 'js'}
},
});
System.import('app/main').then(null,
console.error.bind(console));
</script>
}
|
Note : Use
systemjs: System.import to add the compiled typescript to the HTML.
▋Result
▋What’s next?
In the next
tutorial, we will create a SPA for create/update/delete/see detail.
▌Github
▌Reference
沒有留言:
張貼留言