TRUNGTQ

Think Big, Act Small, Fail Fast and Learn Rapidly

NAVIGATION - SEARCH

CRUD USING .NET CORE 1.0, ANGULARJS2, WEBAPI

In our previous article we have seen how to startup with .Net Core. In this article we will take a look on database operation according to previous sample application based previous concept.

If you are new to .Net Core, Please read previous post about .Net Core Startup

In this article we are going to explore,

  1. Create Database
  2. Use Entity Framework Core (Db First Approach),
    1. Overview EF Core
    2. Install Entity Framework
    3. Create Models
    4. Configure EF Service
  3. Use MVC 6
    1. Overview MVC6
    2. Use WebAPI
  4. Use AngularJS2
    1. Component,
    2. Route
    3. Service
  5. Configure Server
    1. Run App inside/outside IIS

Let’s get started with step by step:

Create Database Before we get started with IDE lets create a new database using SSMS2014. Name it as PhoneBook.

Create a table Named Contacts, copy & run the below script in SSMS2014

USE [PhoneBook]
GO

/****** Object:  Table [dbo].[Contacts]    Script Date: 8/7/2016 11:28:55 AM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Contacts](
	[ContactID] [int] IDENTITY(1,1) NOT NULL,
	[FirstName] [nvarchar](50) NULL,
	[LastName] [nvarchar](50) NULL,
	[Phone] [nvarchar](50) NULL,
	[Email] [nvarchar](50) NULL,
 CONSTRAINT [PK_Contacts] PRIMARY KEY CLUSTERED 
(
	[ContactID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
 

Let’s get started, following our previous topic I am going to use previous sample application, open it with Visual Studio 2015.

core_crud_1

It will automatically started restoring the dependencies. Build & run it. The application is working perfectly.

Install Entity Framework:Before install let’s have an overview on EF Core new Features:

  • Modelling: This includes Basic modelling, Data annotations, Relationships and much more.
  • Change Tracking:This includes Accessing tracked state, Snapshot, Notification change tracking.
  • SaveChanges: This includes Basic save functionality,Async SaveChanges,Transactions.
  • Query: This includes Basic LINQ support, Async query, Raw SQL queries
  • Database schema management: This includes Database creation/deletion APIs, Relational database migrations, and Reverse engineer from database.
  • Database providers: This includes EntityFramework.SqlServer, Sqlite, InMemory
  • Platforms: Supports Universal Windows Platform (UWP), .NET Core, Full .NET

Get more details about EF Core. Let’s add folders for Entity models in our sample app solution. core_crud_3

DbEntities: for model entities. The installation of EF is pretty much simple. Open project.json file, point tools section modify the section with below line.

"Microsoft.EntityFrameworkCore.SqlServer": "1.0.0",
"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final",
"Microsoft.EntityFrameworkCore.SqlServer.Design": "1.0.0"

core_crud_4

Save changes after modification.

core_crud_5

Packages will automatically restored. Let’s get explanation what are those.

EntityFrameworkCore.SqlServer: Database Provider, that allows Entity Framework Core to be used with Microsoft SQL Server.

EntityFrameworkCore.Tools: Command line tool for EF Core. Includes Commands

For Package Manager Console:

  • Scaffold-DbContext,
  • Add-Migration,
  • Udate-Database

For Command Window:

  • dotnet ef dbcontext scaffold

We will see how to use both command. EntityFrameworkCore.SqlServer.Design: Design-time, that allows Entity Framework Core functionality (EF Core Migration) to be used with Microsoft SQL Server. To access the Command line tools we need to add EntityFrameworkCore.Tools intools section of our project.json.

"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"

core_crud_6

Save changes after modification. Command in Package Manager Console:Open package manager console.

core_crud_7

Input below command then hit enter,

Scaffold-DbContext "Server=DESKTOP-4T79RA1;Database=PhoneBook;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models/DbEntities

 core_crud_8core_crud_9

Command in Command Window:Open Command Window navigate to project directory, type

D:\Article\ASP-CORE\CRUD\CoreMVCAngular2\src\CoreMVCAngular>dotnet ef –help

Here a list of option will be shown in command window, we are going to use dbcontext in Commands.

core_crud_10

NextInput below command then hit enter,

D:\Article\ASP-CORE\CRUD\CoreMVCAngular2\src\CoreMVCAngular>dotnet ef dbcontext scaffold "Server=DESKTOP-4T79RA1;Database=PhoneBook;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer --output-dir Models/CwEntities

core_crud_11

Here is a screen shot of both process that execute & generate models. We will keep DbEntities folder to work with & will delete the other folder.

core_crud_12

Configure EF Service: In PhoneBookContext Class add constructor

public PhoneBookContext(DbContextOptions<PhoneBookContext> options) :
       base(options)
{
}
 

In Startup class we need to enable EF services providing the connectionstring to

public void ConfigureServices(IServiceCollection services)
{
  services.AddMvc();
  var connection = @"Server=DESKTOP-4T79RA1;Database=PhoneBook;Trusted_Connection=True;";
  services.AddDbContext<PhoneBookContext>(options => options.UseSqlServer(connection));
}
 

We have configure the EF services in our application, next we will work with MVC6 that is included in ASP.NET Core.

MVC 6:We have already discuss about MVC6 in our previous post, let’s have an overview on MVC6 new Features, once again:

  1. MVC+Web API+Web Pages = MVC6
  2. No System.Web
  3. Web pages & HTTP services is Unified
  4. Dependency injection built in
  5. Dynamic code compilation (Roslyn compiler)
  6. Open source &
  7. Support cross-platform build & run.
  8. Can be hosted in IIS or self-hosted(Outside IIS)

Ok, now let’s add a WebApi Controller to perform CRUD operation to database table. core_crud_13 In Solution Explorer add a new api folder, right click on it > Add New Item > Web API Controller Class > Add. Modify the initial template.

API Controller

[Route("api/[controller]")]
public class ContactController : Controller
{
    private PhoneBookContext _ctx = null;
    public ContactController(PhoneBookContext context)
    {
        _ctx = context;
    }
}
 

core_crud_14

You may notice that there is a new pattern [ ] in MVC6 attribute route, which is [RouteToken]. This mean that the route token is automatically take the controller name.

Like [Route("api/[controller]")] > [Route("api/Contact")]

Another thing is, we know Web API produces XML by default, now in MVC 6 we can set an attribute to change default produces to JSON type by putting attribute in Class label or on method label. In our case we have set it on method label.

[HttpGet("GetContact"), Produces("application/json")]

GET

// GET: api/Contact/GetContact
[HttpGet("GetContact"), Produces("application/json")]
public async Task<object> GetContact()
{
    List<Contacts> contacts = null;
    object result = null;
    try
    {
        using (_ctx)
        {
            contacts = await _ctx.Contacts.ToListAsync();
            result = new
            {
                contacts
            };
        }
    }
    catch (Exception ex)
    {
        ex.ToString();
    }
    return result;
}
 

POST

// POST api/Contact/PostContact
[HttpPost, Route("PostContact")]
public async Task<object> PostContact([FromBody]Contacts model)
{
    object result = null; int message = 0;
    if (model == null)
    {
        return BadRequest();
    }
    using (_ctx)
    {
        using (var _ctxTransaction = _ctx.Database.BeginTransaction())
        {
            try
            {
                _ctx.Contacts.Add(model);
                await _ctx.SaveChangesAsync();
                _ctxTransaction.Commit();
                message = (int)responseMessage.Success;
            }
            catch (Exception e)
            {
                _ctxTransaction.Rollback();
                e.ToString();
                message = (int)responseMessage.Error;
            }

            result = new
            {
                message
            };
        }
    }
    return result;
}
 

PUT

// PUT api/Contact/PutContact/5
[HttpPut, Route("PutContact/{id}")]
public async Task<object> PutContact(int id, [FromBody]Contacts model)
{
    object result = null; int message = 0;
    if (model == null)
    {
        return BadRequest();
    }
    using (_ctx)
    {
        using (var _ctxTransaction = _ctx.Database.BeginTransaction())
        {
            try
            {
                var entityUpdate = _ctx.Contacts.FirstOrDefault(x => x.ContactId == id);
                if (entityUpdate != null)
                {
                    entityUpdate.FirstName = model.FirstName;
                    entityUpdate.LastName = model.LastName;
                    entityUpdate.Phone = model.Phone;
                    entityUpdate.Email = model.Email;

                    await _ctx.SaveChangesAsync();
                }
                _ctxTransaction.Commit();
                message = (int)responseMessage.Success;
            }
            catch (Exception e)
            {
                _ctxTransaction.Rollback(); e.ToString();
                message = (int)responseMessage.Error;
            }

            result = new
            {
                message
            };
        }
    }
    return result;
}
 

DELETE

// DELETE api/Contact/DeleteContactByID/5
[HttpDelete, Route("DeleteContactByID/{id}")]
public async Task<object> DeleteContactByID(int id)
{
    object result = null; int message = 0;
    using (_ctx)
    {
        using (var _ctxTransaction = _ctx.Database.BeginTransaction())
        {
            try
            {
                var idToRemove = _ctx.Contacts.SingleOrDefault(x => x.ContactId == id);
                if (idToRemove != null)
                {
                    _ctx.Contacts.Remove(idToRemove);
                    await _ctx.SaveChangesAsync();
                }
                _ctxTransaction.Commit();
                message = (int)responseMessage.Success;
            }
            catch (Exception e)
            {
                _ctxTransaction.Rollback(); e.ToString();
                message = (int)responseMessage.Error;
            }

            result = new
            {
                message
            };
        }
    }
    return result;
}
 

So our Web API is ready to dealing with data to database, it’s time to work with client side scripting.  

AngularJS2: Our WebAPI is ready to deal with data from server. Now we are going to work in client-side code with typescript (.ts) files. First of all we need to create a master page to present our views in it. core_crud_15

Then we need to point this html file while app start, so let’s go to the startup.cs file to add below code snippet. This is the configuration for the default files Middleware.

Startup.cs

// app-specific root page(Index.html)
DefaultFilesOptions options = new DefaultFilesOptions();
options.DefaultFileNames.Clear();
options.DefaultFileNames.Add("/Index.html");

need to add library

using Microsoft.AspNetCore.Builder;

Now add script library reference to the html page & define view point to load our app component views.

<spa-app>
   <p>
      <img src="img/ajax_small.gif" />  Please wait ...
   </p>
</spa-app>

Then we need to reference our bootstrap file in our page, that import & enable the our angular script to the page.

<script>
   System.config({ packages: { 'app': { defaultExtension: 'js' } }, });
   System.import('app/main').then(null, console.error.bind(console));
</script

Let’s put together all those in Index.html file.

Index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title></title>

    <base href="/">
    <script>document.write('<base href="' + document.location + '" />');</script>
    <script src="../lib-npm/es6-shim/es6-shim.js"></script>
    <script src="../lib-npm/angular2/angular2-polyfills.js"></script>
    <script src="../lib-npm/systemjs/system.src.js"></script>
    <script src="../lib-npm/rxjs/Rx.js"></script>
    <script src="../lib-npm/angular2/angular2.js"></script>
    <script src="../lib-npm/angular2/router.js"></script>
    <script src="../lib-npm/angular2/http.js"></script>

    <link href="../lib/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
    <div class="container">
        <spa-app>
            <p>
                <img src="img/ajax_small.gif" />  Please wait ...
            </p>
        </spa-app>

    </div>
    <script src="../lib/jquery/dist/jquery.min.js"></script>
    <script src="../lib/bootstrap/dist/js/bootstrap.min.js"></script>
    <script>
        System.config({ packages: { 'app': { defaultExtension: 'js' } }, });
        System.import('app/main').then(null, console.error.bind(console));
    </script>
</body>
</html>
 

  Bootstrap, Model, Component & Route Main.ts

/*This is the spa bootstrap File*/

//---------Import Angular2------------
import {bootstrap}    from 'angular2/platform/browser';
import {enableProdMode, provide} from 'angular2/core';

//---------Import External Components(Main Component)---------
import {MainComponent} from './app.component';

//---------Bootstrap Component---------
enableProdMode();
bootstrap(MainComponent);
App.component.ts

Hide   Shrink    Copy Code
/*Component Default view For SpaRoute */

//---------Import Angular2------------
import {Component, provide} from 'angular2/core';
import {RouteConfig, ROUTER_DIRECTIVES, 
        ROUTER_PROVIDERS, LocationStrategy, 
        HashLocationStrategy, APP_BASE_HREF}                  from 'angular2/router';
 
//---------Import External Components---------
import {Home} from './home/home.component';
import {Contact} from './contact/contact.component';

//---------Declare Components---------
@Component({
    selector: 'spa-app',
    directives: [ROUTER_DIRECTIVES], //decorate link 
    templateUrl: 'app/main.view.html',
    providers: [
        ROUTER_PROVIDERS,
        //provide(APP_BASE_HREF, { useValue: '/' })
        provide(LocationStrategy, { useClass: HashLocationStrategy })
    ]
})

//---------Declare Route Config---------
@RouteConfig([
    { path: '/', name: 'Home', component: Home, useAsDefault: true },
    { path: '/Contact/...', name: 'Contact', component: Contact }
])


//---------Export This Component Class---------
export class MainComponent {
    title: string;
    constructor() {
        this.title = 'Welcome to [.NetCore+MVC6+Angular2] SPA';
    }
}


  Home.ts

import {Component} from 'angular2/core';

@Component({
    selector: 'home',
    templateUrl: `app/home/home.view.html`
})
export class Home {
    constructor() {   
    }
}
Contact.model.ts

Hide   Copy Code
export class ContactModel {
    contactId: number;
    firstName: string;
    lastName: string;
    phone: string;
    email: string;
}


Contact.component.ts

//---------Import Angular2------------
import {Component}                                            from 'angular2/core';
import {ROUTER_DIRECTIVES, RouteConfig}                       from 'angular2/router';

//---------Import External Components---------
import {ContactMain}                                          from './contact.main';

//---------Declare Components---------
@Component({
    selector: 'contacts',
    template: `<router-outlet></router-outlet>`,
    directives: [ROUTER_DIRECTIVES]
})
@RouteConfig([
    { path: '/', name: 'ManageContact', component: ContactMain, useAsDefault: true },
])
export class Contact {
    constructor() { }
}
 

  Contact.main.ts

//---------Import Angular2------------
import {Component, OnInit}                                     from 'angular2/core';
import {HTTP_PROVIDERS, Http}                                  from 'angular2/http';
import {ROUTER_DIRECTIVES, RouteConfig}                        from 'angular2/router';
import {FORM_DIRECTIVES,
    FormBuilder, Control, ControlGroup, Validators}            from 'angular2/common';

//---------Import External Components---------
import {ContactModel}                                          from './contact.model';
import {ContactService}                                        from './contact.service';
import {customvalidators}                                      from './customvalidators';

//---------Declare Components---------
@Component({
    selector: 'contact-list',
    templateUrl: `app/contact/contact.view.html`,
    directives: [ROUTER_DIRECTIVES, FORM_DIRECTIVES],
    providers: [ContactService, HTTP_PROVIDERS]
})

//---------Export This Component Class---------
export class ContactMain implements OnInit {

    public resmessage: string;
    public addmessage: string;
    public listmessage: string;
    public contact: ContactModel;
    public contacts: ContactModel[];
    public editContactId: any

    //Form Control
    contactForm: ControlGroup;
    firstName: Control;
    email: Control;
    phone: Control;

    //Constructor
    constructor(private builder: FormBuilder,
        private contactService: ContactService) {
        this.addmessage = 'Add New Contact';
        this.listmessage = 'All Contact';
        this._formGroup();
    }

    ngOnInit() {
        this.resmessage = "";
        this.editContactId = 0;
        this.getContacts();
    }

    //Form Group
    _formGroup() {
        this.firstName = new Control('', Validators.required);
        this.email = new Control('', Validators.compose([Validators.required, customvalidators.emailValidator]));
        this.phone = new Control('');

        this.contactForm = this.builder.group({
            firstName: this.firstName,
            email: this.email,
            phone: this.phone
        });
    }

    //Get All 
    getContacts() {
        //debugger
        this.contactService.getContacts().subscribe(
            contacts => this.contacts = contacts
        );
    }

    //Save Form
    saveContact(contact) {
        //debugger
        this.contactService.saveContact(contact)
            .subscribe(response => {
                this.resmessage = response;
                this.getContacts();
                this.reset();
            });
    }

    //Get by ID
    editContact(e, m) {
        //debugger
        e.preventDefault();
        this.editContactId = m.contactId;
        this.contactService.getContactByID(m.contactId)
            .subscribe(response => {
                this.contact = response;
                this.firstName.updateValue(this.contact.firstName);
                this.email.updateValue(this.contact.email);
                this.phone.updateValue(this.contact.phone);
            });
    }

    //Save Form
    updateContact(contact: any) {
        //debugger
        if (this.editContactId > 0) {
            this.contactService.updateContact(contact, this.editContactId)
                .subscribe(response => {
                    this.resmessage = response;
                    this.getContacts();
                    this.reset();
                });
        }
    }

    //Delete
    deleteContact(e, m) {
        //debugger
        e.preventDefault();
        var IsConf = confirm('You are about to delete ' + m.firstName + '. Are you sure?');
        if (IsConf) {
            this.contactService.deleteContact(m.contactId)
                .subscribe(response => {
                    this.resmessage = response;
                    this.getContacts();
                });
        }
    }

    reset() {
        this.editContactId = 0;
        this._formGroup();
    }
}
 

Let’s take a closer look at below code snippet, we have the service method call in hare, but the unknown term Subscribe -What is it for? Below we have a simple explanation.

this.contactService.getContacts().subscribe(
            contacts => this.contacts = contacts
        );

Subscribe:The subscriber function to be passed to the Observable constructor.  

Services In our service file we have Http service [Get, GetByID, Post, Put, Delete] that connect with WebAPI to perform operation Create, Read, Update & Delete. GET ALL:Performs a request with `get` http method.For Collection of Object

/Get
    getContacts(): Observable<ContactModel[]> {
        //debugger
        return this._http.get(this._getUrl)
            .map(res => <ContactModel[]>res.json())
            .catch(this.handleError);
    }

GET By ID:Performs a request with `get` http method.For Single Object

//GetByID
    getContactByID(id: string): Observable<ContactModel> {
        //debugger
        var getByIdUrl = this._getByIdUrl + '/' + id;
        return this._http.get(getByIdUrl)
            .map(res => <ContactModel>res.json())
            .catch(this.handleError);
    }

POST:Performs a request with `post` http method.

//Post
    saveContact(contact: ContactModel): Observable<string> {
        //debugger
        let body = JSON.stringify(contact);
        let headers = new Headers({ 'Content-Type': 'application/json' });
        let options = new RequestOptions({ headers: headers });

        //http.post(url: string, body: string, options ?: RequestOptionsArgs): Observable<Response>
        return this._http.post(this._saveUrl, body, options)
            .map(res => res.json().message)
            .catch(this.handleError);
    }

PUT:Performs a request with `put` http method.

//Put
    updateContact(contact: ContactModel, id: string): Observable<string> {
        //debugger
        var updateUrl = this._updateUrl + '/' + id;
        var body = JSON.stringify(contact);
        var headers = new Headers();
        headers.append('Content-Type', 'application/json');

        //http.post(url: string, body: string, options ?: RequestOptionsArgs): Observable<Response>
        return this._http.put(updateUrl, body, { headers: headers })
            .map(response => response.json().message)
            .catch(this.handleError);
    }

DELETE:Performs a request with `delete` http method.

//Delete
    deleteContact(id: string): Observable<string> {
        //debugger
        var deleteByIdUrl = this._deleteByIdUrl + '/' + id

        //http.post(url: string, options ?: RequestOptionsArgs): Observable<Response>
        return this._http.delete(deleteByIdUrl)
            .map(response => response.json().message)
            .catch(this.handleError);
    }

Observable : [Observable<T>] A representation of any set of values over any amount of time. This the most basic building block of RxJS. Let’s put it together in Contact.service file.

Contact.service.ts

import {Injectable, Component}                            from 'angular2/core';
import {Http, Request, RequestMethod, Response,
    RequestOptions, Headers}                              from 'angular2/http';
import 'rxjs/Rx';
import {Observable}                                       from 'rxjs/Observable';
import {ContactModel}                                     from './contact.model';

@Component({
    providers: [Http]
})

@Injectable()
export class ContactService {
    public headers: Headers;
    constructor(private _http: Http) {
    }

    public _saveUrl: string = '/api/Contact/PostContact/';
    public _updateUrl: string = '/api/Contact/PutContact/';
    public _getUrl: string = '/api/Contact/GetContact/';
    public _getByIdUrl: string = '/api/Contact/GetContactByID/';
    public _deleteByIdUrl: string = '/api/Contact/DeleteContactByID/';

    //Get
    getContacts(): Observable<ContactModel[]> {
        //debugger
        return this._http.get(this._getUrl)
            .map(res => <ContactModel[]>res.json())
            .catch(this.handleError);
    }

    //GetByID
    getContactByID(id: string): Observable<ContactModel> {
        //debugger
        var getByIdUrl = this._getByIdUrl + '/' + id;
        return this._http.get(getByIdUrl)
            .map(res => <ContactModel>res.json())
            .catch(this.handleError);
    }

    //Post
    saveContact(contact: ContactModel): Observable<string> {
        //debugger
        let body = JSON.stringify(contact);
        let headers = new Headers({ 'Content-Type': 'application/json' });
        let options = new RequestOptions({ headers: headers });

        //http.post(url: string, body: string, options ?: RequestOptionsArgs): Observable<Response>
        return this._http.post(this._saveUrl, body, options)
            .map(res => res.json().message)
            .catch(this.handleError);
    }

    //Put
    updateContact(contact: ContactModel, id: string): Observable<string> {
        //debugger
        var updateUrl = this._updateUrl + '/' + id;
        var body = JSON.stringify(contact);
        var headers = new Headers();
        headers.append('Content-Type', 'application/json');

        //http.post(url: string, body: string, options ?: RequestOptionsArgs): Observable<Response>
        return this._http.put(updateUrl, body, { headers: headers })
            .map(response => response.json().message)
            .catch(this.handleError);
    }

    //Delete
    deleteContact(id: string): Observable<string> {
        //debugger
        var deleteByIdUrl = this._deleteByIdUrl + '/' + id

        //http.post(url: string, options ?: RequestOptionsArgs): Observable<Response>
        return this._http.delete(deleteByIdUrl)
            .map(response => response.json().message)
            .catch(this.handleError);
    }

    private handleError(error: Response) {
        return Observable.throw(error.json().error || 'Opps!! Server error');
    }
}

Let’s discus about form in angular2, there are two strategy of angular2 form

  1. Template-driven
  2. Model-driven

 Template-driven In template-driven form directive are added declaratively in the template.

<input id="firstName" type="text"
       class="form-control"
       placeholder="FirstName" [ngFormControl]="firstName" required>

Noticed that the validator is added declaratively with the input element “required”.  

Model-driven In our sample app we have used model-driven form that has ngFormModel & ngFormControl. Here ngFormControl is bind with input element to get the input values through the control.

ngFormModel:binding it to a controller variable “contactForm”

<form [ngFormModel]="contactForm">

ngFormControl

<input id="firstName" type="text" 
                       class="form-control" 
                       placeholder="FirstName" [ngFormControl]="firstName">

ControlGroup is contain of several Controls.

//Form Control
contactForm: ControlGroup;
firstName: Control;
email: Control;
phone: Control;

An Injected FormBulder use the builder to create the control group which is pass as key value pairs.

private builder: FormBuilder

//Form Group
_formGroup() {
    //Set Initial Values to the Control & Validators
    this.firstName = new Control('', Validators.required);
    this.email = new Control('', Validators.compose([Validators.required, customvalidators.emailValidator]));
    this.phone = new Control('');

    //Pass the grouped controls as key value pairs
    this.contactForm = this.builder.group({
        firstName: this.firstName,
        email: this.email,
        phone: this.phone
    });
}

The validations are also checked in our component. Below we have our Model-driven complete form. Form

<form [ngFormModel]="contactForm">
            <div class="form-group" [ngClass]="{ 'has-error' : !firstName.valid }">
                <label class="control-label" for="firstName">Username</label>
                <em *ngIf="!firstName.valid">*</em>
                <input id="firstName" type="text" 
                       class="form-control" 
                       placeholder="FirstName" [ngFormControl]="firstName">
            </div>

            <div class="form-group" [ngClass]="{ 'has-error' : !email.valid }">
                <label class="control-label" for="email">Email</label>
                <em *ngIf="!email.valid">*</em>
                <input id="email" type="email" 
                       class="form-control" 
                       placeholder="Email" [ngFormControl]="email">
            </div>

            <div class="form-group">
                <label class="control-label" for="phone">Phone</label>
                <input id="phone" type="text" class="form-control" placeholder="Phone" [ngFormControl]="phone">
            </div>

            <div class="form-group">
                <button type="submit" class="btn btn-danger" (click)="reset()">Reset</button>
                <button type="submit" class="btn btn-primary" (click)="saveContact(contactForm.value)" 
                        *ngIf="editContactId == 0" 
                        [disabled]="!contactForm.valid">Create</button>
                <button type="submit" class="btn btn-success" (click)="updateContact(contactForm.value)" 
                        *ngIf="editContactId > 0" 
                        [disabled]="!contactForm.valid">Update</button>
            </div>
</form>
 

  Here is the complete contact view page which we have used in our application.

Contact.view.html

<div class="row">

    <div class="col-sm-4">
        <h3>Phone Book {{addmessage}}</h3>
        <form [ngFormModel]="contactForm">
            <div class="form-group" [ngClass]="{ 'has-error' : !firstName.valid }">
                <label class="control-label" for="firstName">Username</label>
                <em *ngIf="!firstName.valid">*</em>
                <input id="firstName" type="text" 
                       class="form-control" 
                       placeholder="FirstName" [ngFormControl]="firstName">
            </div>

            <div class="form-group" [ngClass]="{ 'has-error' : !email.valid }">
                <label class="control-label" for="email">Email</label>
                <em *ngIf="!email.valid">*</em>
                <input id="email" type="email" 
                       class="form-control" 
                       placeholder="Email" [ngFormControl]="email">
            </div>

            <div class="form-group">
                <label class="control-label" for="phone">Phone</label>
                <input id="phone" type="text" class="form-control" placeholder="Phone" [ngFormControl]="phone">
            </div>

            <div class="form-group">
                <button type="submit" class="btn btn-danger" (click)="reset()">Reset</button>
                <button type="submit" class="btn btn-primary" (click)="saveContact(contactForm.value)" 
                        *ngIf="editContactId == 0" 
                        [disabled]="!contactForm.valid">Create</button>
                <button type="submit" class="btn btn-success" (click)="updateContact(contactForm.value)" 
                        *ngIf="editContactId > 0" 
                        [disabled]="!contactForm.valid">Update</button>
            </div>
        </form>
        <span class="warning">{{resmessage}}</span>
    </div>
    <div class="col-sm-8">
        <h3>Phone Book {{listmessage}}</h3>
        <table style="width:100%" class="table table-striped">
            <tr>
                <th>ID</th>
                <th>Firstname</th>
                <th>Email</th>
                <th>Phone</th>
                <th>Option</th>
            </tr>
            <tr *ngFor="#contact of contacts">
                <td>{{ contact.contactId }}</td>
                <td>{{ contact.firstName }}</td>
                <td>{{ contact.email }}</td>
                <td>{{ contact.phone }}</td>
                <td>
                    <a href="javascript:void(0)"
                       (click)="deleteContact($event, contact)"
                       class="btn btn-danger btn-xs pull-right">Delete</a>
                    <a href="javascript:void(0)"
                       (click)="editContact($event, contact)"
                       class="btn btn-primary btn-xs pull-right">Edit</a>
                </td>
            </tr>
        </table>
    </div>
</div>
 

  This is all about from our angular section in our sample app, that we have used to perform client-end operation, now it’s time to build & run the application. Next we will get overview on server configuration.  

ConfigureServer: Outside IIS (Weblistener):We can host & run our application without an IIS environment, we need to add command object that tell the hosting to use the HTTP server weblistener (Windows-only).

"commands": {
    "OutsideIIS": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.Weblistener --server.urls http://localhost:5001"
  },

Make sure the dependencies is exist

"Microsoft.AspNetCore.Server.WebListener": "0.1.0"

Now go to solution explorer right click project > properties > Debug , change the profile to OutsideIIS. core_crud_16 Set launch URL, then save & run the application. core_crud_17 Server will start with hosting environment details

core_crud_18

The application is running on url http://localhost:5000 with details request info.

core_crud_19

Inside IIS (Kestrel):Kestrel is a cross-platform web server which is run behind IIS or Nginx.

core_crud_20

Change to IIS Express from navigation bar dropdown list to run the application using IIS. Ok let’s run our application to see the way how it’s work.

Output: Here we can see the application output with welcome message & the data is listed from the server through our MVC6 –WebAPI. Here we can perform CRUD operation with required validation.  

core_crud_21

Hope this will help :)

LINK: https://www.codeproject.com/Articles/1118189/CRUD-USING-NET-CORE-ANGULARJS-WEBAPI

 

ASP.NET Core, Angular2 Shopping Cart Using Web API And EF 1.0.1

In this article let’s see how to create a shopping cart using ASP.NET Core, Angular 2, Entity Framework 1.0.1 and Web API with Template pack .

Introduction

In this article let’s see how to create a shopping cart using ASP.NET Core, Angular 2, Entity Framework 1.0.1 and Web API with Template pack .

Note

Kindly read our previous article which  explains in depth about Getting Started with ASP.NET Core Template Pack

In this article let’s see,

  • Creating sample Database and ItemDetails Table in SQL Server to display in our web application.
  • Creating ASP.NET Core Angular 2 Starter Application (.NET Core) using Template pack
  • Creating EF, DBContext Class and Model Class.
  • Creating WEB API
  • Creating our Component TypeScript file to get WEB API JSON result using Http Module.
  • Filtering Items by Item Name. From Item textbox keyup event display the items by search name.
  • Selecting and Adding Items to Shopping Cart.
  • Displaying Total Price, Total Qty and Grand Price Total in Shopping Cart.
  • Displaying Shopping Cart Details.

This article will explain in detail about how to create a Simple Shopping cart using ASP.NET Core, Angular2, Web API and EF with Template Pack. 

In this Shopping Cart Demo application, we have 3 parts

  • Display All Items and Filter Items in HTML Table using Angular2 from WEB API.
  • Display the Selected Items in details before add to Shopping Cart
  • Add the Selected Item to Shopping Cart. Show Price, Quantity and Grand Total of all items in Shopping cart. 

Display All Items and Filter Items

First, we display all item details in the Shopping page using Angular2. All the Item details will be loaded from WEB API. User can also filter the items by Item Name. When users enter any character in the item Name Filter textbox, the related item details will be loaded dynamically from the database to the shopping page. 

Display the Selected Items in details

When user clicks on Image name we display the detailed Item details at the top to add the selected item to shopping cart. When user clicks on the “Add to cart” button the selected item will be added to the Shopping Cart.

Shopping Cart Details

When user clicks on “Add Item to Cart” button, the selected item will be added to the Shopping cart, before adding to cart we check if the Item is already added to the cart. If the item is already added to the cart then we will increment the quantity in Shopping Cart, If the item is not added then newly selected items will be added to Shopping Cart. In the Shopping Cart, we also display the number of Items  that have been added in the shopping cart. In the Shopping cart we also calculate the total Quantity, Total Price and Grand Price of total shopping details which will be displayed at the end of Shopping Item details.

Prerequisites

Make sure you have installed all the prerequisites in your computer. If not, then download and install all, one by one.

  1. First, download and install Visual Studio 2015 with Update 3 from this link.
  2. If you have Visual Studio 2015 and have not yet updated with update 3, download and install the Visual Studio 2015 Update 3 from this link
  3. Download and install .NET Core 1.0.1 
  4. Download and install TypeScript 2.0 
  5. Download and install Node.js v4.0 or above. I have installed V6.9.1 (Download link).
  6. Download and install Download ASP.NET Core Template Pack visz file from this link

Using the code

Step 1 Create a Database and Table

We will create a ItemDetails table to be used for the Shopping Cart Grid data binding.

The following is the script to create a database, table and sample insert query.

Run this script in your SQL Server. I have used SQL Server 2014. 

-- =============================================  
-- Author : Shanu  
-- Create date : 2017-02-03
-- Description : To Create Database,Table and Sample Insert Query  
-- Latest  
-- Modifier : Shanu  
-- Modify date : 2017-02-03  
-- ============================================= 
--Script to create DB,Table and sample Insert data 
USE MASTER 
GO 
-- 1) Check for the Database Exists .If the database is exist then drop and create new DB 
IF EXISTS (SELECT [name] FROM sys.databases WHERE [name] = 'ShoppingDB' ) 
DROP DATABASE ShoppingDB 
GO 
 
CREATE DATABASE ShoppingDB 
GO 
 
USE ShoppingDB 
GO 
 
-- 1) //////////// ItemDetails table 
-- Create Table ItemDetails,This table will be used to store the details like Item Information  
 
IF EXISTS ( SELECT [name] FROM sys.tables WHERE [name] = 'ItemDetails' ) 
DROP TABLE ItemDetails 
GO 
 
CREATE TABLE ItemDetails 
( 
Item_ID int identity(1,1), 
Item_Name VARCHAR(100) NOT NULL, 
Item_Price int NOT NULL, 
Image_Name VARCHAR(100) NOT NULL, 
Description VARCHAR(100) NOT NULL, 
AddedBy VARCHAR(100) NOT NULL, 
CONSTRAINT [PK_ItemDetails] PRIMARY KEY CLUSTERED  
(  
[Item_ID] ASC  
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]  
) ON [PRIMARY]  
 
GO 
 
-- Insert the sample records to the ItemDetails Table 
Insert into ItemDetails(Item_Name,Item_Price,Image_Name,Description,AddedBy) values('Access Point',950,'AccessPoint.png','Access Point for Wifi use','Shanu') 
Insert into ItemDetails(Item_Name,Item_Price,Image_Name,Description,AddedBy) values('CD',350,'CD.png','Compact Disk','Afraz') 
Insert into ItemDetails(Item_Name,Item_Price,Image_Name,Description,AddedBy) values('Desktop Computer',1400,'DesktopComputer.png','Desktop Computer','Shanu') 
Insert into ItemDetails(Item_Name,Item_Price,Image_Name,Description,AddedBy) values('DVD',1390,'DVD.png','Digital Versatile Disc','Raj') 
Insert into ItemDetails(Item_Name,Item_Price,Image_Name,Description,AddedBy) values('DVD Player',450,'DVDPlayer.png','DVD Player','Afraz') 
Insert into ItemDetails(Item_Name,Item_Price,Image_Name,Description,AddedBy) values('Floppy',1250,'Floppy.png','Floppy','Mak') 
Insert into ItemDetails(Item_Name,Item_Price,Image_Name,Description,AddedBy) values('HDD',950,'HDD.png','Hard Disk','Albert') 
Insert into ItemDetails(Item_Name,Item_Price,Image_Name,Description,AddedBy) values('MobilePhone',1150,'MobilePhone.png','Mobile Phone','Gowri') 
Insert into ItemDetails(Item_Name,Item_Price,Image_Name,Description,AddedBy) values('Mouse',399,'Mouse.png','Mouse','Afraz') 
Insert into ItemDetails(Item_Name,Item_Price,Image_Name,Description,AddedBy) values('MP3 Player ',897,'MultimediaPlayer.png','Multi MediaPlayer','Shanu') 
Insert into ItemDetails(Item_Name,Item_Price,Image_Name,Description,AddedBy) values('Notebook',750,'Notebook.png','Notebook','Shanu') 
Insert into ItemDetails(Item_Name,Item_Price,Image_Name,Description,AddedBy) values('Printer',675,'Printer.png','Printer','Kim') 
Insert into ItemDetails(Item_Name,Item_Price,Image_Name,Description,AddedBy) values('RAM',1950,'RAM.png','Random Access Memory','Jack') 
Insert into ItemDetails(Item_Name,Item_Price,Image_Name,Description,AddedBy) values('Smart Phone',679,'SmartPhone.png','Smart Phone','Lee') 
Insert into ItemDetails(Item_Name,Item_Price,Image_Name,Description,AddedBy) values('USB',950,'USB.png','USB','Shanu') 
 
select * from ItemDetails
 

Step 2- Create ASP.NET Core Angular 2 application

After installing all the prerequisites listed above and ASP.NET Core Template, click Start >> Programs >> Visual Studio 2015 >> Visual Studio 2015, on your desktop. Click New >> Project. Select Web >> ASP.NET Core Angular 2 Starter. Enter your project name and click OK.

After creating ASP.NET Core Angular 2 application, wait for a few seconds. You will see that all the dependencies are automatically restored.

We will be using all this in our project to create, build and run our Angular 2 with ASP.NET Core Template Pack, WEB API and EF 1.0.1

Step 3 Creating Entity Freamework 

Add Entity Framework Packages

To add our Entity Framework Packages in our ASP.NET Core application. Open the Project.JSON File and in dependencies add the below line.

Note

Here we have used EF version 1.0.1. 

"Microsoft.EntityFrameworkCore.SqlServer": "1.0.1", 
"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final" 

When we save the project,.json file we can see the Reference was been Restoring.

After few second we can see Entity framework package has been restored and all reference has been added.

Adding Connection String

To add the connection string with our SQL connection open the “appsettings.json” file .Yes this is a JSON file and this file looks like the below Image by default.

In this appsettings.json file add our connection string  

"ConnectionStrings": { 
    "DefaultConnection": "Server=YOURDBSERVER;Database=StudentsDB;user id=SQLID;password=SQLPWD;Trusted_Connection=True;MultipleActiveResultSets=true;" 
  },


Note : change the SQL connection string as per your local connection.

Next step is we create a folder named “Data” to create our model and DBContext class.

Creating Model Class for Item Details

We can create a model by adding a new class file in our Data Folder. Right Click Data folder and click Add>Click Class. Enter the class name as itemDetails and click Add.

Now in this class we first create property variable, add ItemDetails. We will be using this in our WEB API controller.  

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Threading.Tasks; 
using System.ComponentModel.DataAnnotations; 
 
namespace Angular2ASPCORE.Data 
{ 
public class ItemDetails 
    { 
        [Key] 
        public int Item_ID { get; set; } 
 
        [Required] 
        [Display(Name = "Item_Name")] 
        public string Item_Name { get; set; } 
 
        [Required] 
        [Display(Name = "Item_Price")] 
        public int Item_Price { get; set; } 
 
        [Required] 
        [Display(Name = "Image_Name")] 
        public string Image_Name { get; set; } 
 
        [Required] 
        [Display(Name = "Description")] 
        public string Description { get; set; } 
 
        [Required] 
        [Display(Name = "AddedBy")] 
        public string AddedBy { get; set; } 
    } 
}


Creating Database Context

DBContext is Entity Framework Class for establishing connection to database.

We can create a DBContext class by adding a new class file in our Data Folder. Right Click Data folder and click Add>Click Class. Enter the class name as ItemContext and click Add.

In this class we inherit DbContext and created Dbset for our ItemDetails table. 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Threading.Tasks; 
using Microsoft.EntityFrameworkCore; 
 
namespace Angular2ASPCORE.Data 
{ 
    public class ItemContext : DbContext 
    { 
        public ItemContext(DbContextOptions<ItemContext> options) 
            : base(options) { } 
        public ItemContext() { } 
        public DbSet<ItemDetails> ItemDetails { get; set; } 
    } 
}  


Startup.CS

Now we need to add our database connection string and provider as SQL SERVER.To add this we add the below code in Startup.cs file under ConfigureServices method. 

// Add Entity framework . 
            services.AddDbContext<studentContext>(options => 
             options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));


Step 4 Creating Web API

To create our WEB API Controller, right click Controllers folder. Click Add and click New Item.

Click ASP.NET in right side > Click Web API Controller Class. Enter the name as “itemDetailsAPI.cs” and click Add.

In this we are using only Get method to get all the ItemDetails result from database and binding the final result using Angular2 to html file.

Here in this web API we get all ItemDetails and ItemDetails  loaded by condition ItemName. 

[Produces("application/json")] 
    [Route("api/ItemDetailsAPI")]  
    public class ItemDetailsAPI : Controller 
    { 
        private readonly ItemContext _context; 
 
        public ItemDetailsAPI(ItemContext context) 
        { 
            _context = context; 
        } 
 
        // GET: api/values 
 
        [HttpGet] 
        [Route("Details")] 
        public IEnumerable<ItemDetails> GetItemDetails() 
        { 
            return _context.ItemDetails; 
 
        } 
 
 
        // GET api/values/5 
        [HttpGet] 
        [Route("Details/{ItemName}")] 
        public IEnumerable<ItemDetails> GetItemDetails(string ItemName) 
        { 
            //return _context.ItemDetails.Where(i => i.Item_ID == id).ToList(); ; 
            return _cont
      }


To test it we can run our project and copy the get method API path here we can see our API path for get is/api/ItemDetailsAPI/Details

Run the program and paste the above API path to test our output.

To get the Item Details by ItemName, here we can see all the ItemDetails which start from ItemName “DVD” has been loaded.

/api/ItemDetailsAPI/Details/DVD

Working with Angular2

We create all Angular2 related Apps, Modules, Services, Components, and html templates under ClientApp/App folder.

We create “model” folder adding our models and create “shopping” folder under app folder to create our typescript and html file for displaying Item details.

Note - Images Folder

First create a folder called “Images” inside the shopping folder. I have used this folder to display all shopping cart images. If you store shopping image in some other path in your code change accordingly.

Step 5 Creating our First Component TypeScript

Right Click on shopping folder and click on add new Item. Select Client-side from left side and select TypeScript File and name the file as “shopping.component.ts” and click Add.

First we create ItemDetails.ts  and CartItemDetails.ts model as typescript file.

ItemDetails.ts 

//// For ItemDetails
export interface ItemDetails {
    Item_ID: number;
    Item_Name: string;
    Item_Price: number;
    Image_Name: string;
    Description: string;
    AddedBy: string;
}  


CartItemDetails.ts 

export class CartItemDetails {
    constructor(
        public CItem_ID: number,
        public CItem_Name: string,
        public CImage_Name: string,
        public CDescription: string,
        public CAddedBy: string,
        public CItem_Price: number,
        public CQty: number,
        public CTotalPrice: number
    ) { }
}  


We import this class in our Shopping.component for binding the result of JSon results.

In students.component.ts file we have three parts first is the

  1. import part
  2. Next is component part
  3. Next we have the class for writing our business logics.

First we import angular files to be used in our component; here we import http for using http client in our Angular2 component. 

In component we have selector and template. Selector is to give a name for this app and in our html file we use this selector name to display in our html page.

In template we give our output html file name. Here we will create one html file as “students.component.html”.

Export Class is the main class where we do all our business logic and variable declaration to be used in our component template. In this class we get the API method result and bind the result to the student array. 

Here in the code part I have commented each section for easy understanding. 

import { Component, Injectable, Inject, EventEmitter, Input, OnInit, Output, NgModule  } from <a href="mailto:'@angular/core'">'@angular/core'</a>; 
import { FormsModule  } from <a href="mailto:'@angular/forms'">'@angular/forms'</a>; 
import { ActivatedRoute, Router } from <a href="mailto:'@angular/router'">'@angular/router'</a>; 
import { BrowserModule } from <a href="mailto:'@angular/platform-browser'">'@angular/platform-browser'</a>;  
import { Http,Headers, Response, Request, RequestMethod, URLSearchParams, RequestOptions } from "@angular/http"; 
import { ItemDetails } from '../model/ItemDetails'; 
import { CartItemDetails } from '../model/CartItemDetails'; 
 
 
@Component({ 
    selector: 'shopping', 
    template: require('./shopping.component.html') 
}) 
 
 
export class shoppingComponent { 
    //Declare Variables to be used 
 
    //To get the WEb api Item details to be displayed for shopping 
    public ShoppingDetails: ItemDetails[] = [];    
    myName: string; 
 
    //Show the Table row for Items,Cart  and Cart Items. 
    showDetailsTable: Boolean = true; 
    AddItemsTable: Boolean = false; 
    CartDetailsTable: Boolean = false; 
    public cartDetails: CartItemDetails[] = []; 
 
    public ImageUrl = require("./Images/CD.png"); 
    public cartImageUrl = require("./Images/shopping_cart64.png"); 
 
 
    //For display Item details and Cart Detail items 
    public ItemID: number; 
    public ItemName: string = ""; 
    public ItemPrice: number = 0; 
    public Imagename: string = ""; 
    public ImagePath: string = ""; 
    public Descrip: string =  "";    
    public txtAddedBy: string = ""; 
    public Qty: number = 0;  
 
    //For calculate Total Price,Qty and Grand Total price 
    public totalPrice: number = 0; 
    public totalQty: number = 0; 
    public GrandtotalPrice: number = 0; 
 
    public totalItem: number = 0; 
 
 
    //Inital Load 
    constructor(public http: Http) { 
        this.myName = "Shanu"; 
        this.showDetailsTable = true;  
        this.AddItemsTable = false; 
        this.CartDetailsTable = false; 
        this.getShoppingDetails(''); 
    } 
 
    //Get all the Item Details and Item Details by Item name 
    getShoppingDetails(newItemName) { 
      
        if (newItemName == "") { 
            this.http.get('/api/ItemDetailsAPI/Details').subscribe(result => { 
                this.ShoppingDetails = result.json(); 
            }); 
        } 
        else { 
            this.http.get('/api/ItemDetailsAPI/Details/' + newItemName).subscribe(result => { 
                this.ShoppingDetails = result.json(); 
            }); 
        } 
    } 
 
    //Get Image Name to bind 
    getImagename(newImage) {  
        this.ImageUrl = require("./Images/" + newImage); 
    } 
 
    // Show the Selected Item to Cart for add to my cart Items. 
    showToCart(Id, Name, Price, IMGNM, Desc,user) 
    { 
        this.showDetailsTable = true; 
        this.AddItemsTable = true; 
        this.CartDetailsTable = false; 
        this.ItemID = Id; 
        this.ItemName = Name; 
        this.ItemPrice = Price; 
        this.Imagename = require("./Images/" + IMGNM); 
        this.ImagePath = IMGNM 
        this.Descrip = Desc; 
        this.txtAddedBy = user; 
    } 
 
    // to Show Items to be added in cart 
    showCart() { 
        this.showDetailsTable = false; 
        this.AddItemsTable = true; 
        this.CartDetailsTable = true; 
        this.addItemstoCart();  
    } 
    // to show all item details 
    showItems() { 
        this.showDetailsTable = true; 
        this.AddItemsTable = false; 
        this.CartDetailsTable = false;       
    } 
 
    //to Show our Shopping Items details 
 
    showShoppingItems() { 
        if (this.cartDetails.length <= 0) 
        { 
            alert("Ther is no Items In your Cart.Add Items to view your Cart Details !") 
            return; 
        } 
        this.showDetailsTable = false; 
        this.AddItemsTable = false; 
        this.CartDetailsTable = true; 
    } 
 
    //Check the Item already exists in Cart,If the Item is exist then add only the quantity else add selected item to cart. 
    addItemstoCart() { 
       
        var count: number = 0; 
        var ItemCountExist: number = 0; 
        this.totalItem = this.cartDetails.length; 
      if (this.cartDetails.length > 0) { 
          for (count = 0; count < this.cartDetails.length; count++) { 
              if (this.cartDetails[count].CItem_Name == this.ItemName) { 
                  ItemCountExist = this.cartDetails[count].CQty + 1; 
                  this.cartDetails[count].CQty = ItemCountExist; 
              } 
          } 
      } 
            if (ItemCountExist <= 0) 
            {  
                this.cartDetails.push( 
                    new CartItemDetails(this.ItemID, this.ItemName, this.ImagePath, this.Descrip, this.txtAddedBy, this.ItemPrice, 1, this.ItemPrice));  
     
            } 
            this.getItemTotalresult(); 
    } 
 
    //to calculate and display the total price information in Shopping cart. 
     getItemTotalresult() { 
    this.totalPrice = 0; 
    this.totalQty = 0; 
    this.GrandtotalPrice = 0; 
    var count: number = 0; 
    this.totalItem = this.cartDetails.length; 
    for (count = 0; count < this.cartDetails.length; count++) { 
        this.totalPrice += this.cartDetails[count].CItem_Price; 
        this.totalQty += (this.cartDetails[count].CQty); 
        this.GrandtotalPrice += this.cartDetails[count].CItem_Price * this.cartDetails[count].CQty; 
    }   
 
} 
 
    //remove the selected item from the cart. 
    removeFromCart(removeIndex) { 
        alert(removeIndex); 
        this.cartDetails.splice(removeIndex, 1); 
 
        this.getItemTotalresult(); 
    } 
}


Step 6 Creating our First Component HTML File

Right Click on shopping folder and click on add new Item. Select Client-side from left side and select html File and name the file as “shopping.component.html” and click Add.

Write the below html code to bind the result in our html page to display all the Shopping Items and Shopping Cart details.. 

<h1>{{myName}} ASP.NET Core , Angular2 Shopping Cart using   Web API and EF 1.0.1    </h1> 
<hr style="height: 1px;color: #123455;background-color: #d55500;border: none;color: #d55500;" /> 
  
 
<p *ngIf="!ShoppingDetails"><em>Loading Student Details please Wait ! ...</em></p> 
 <!--<pre>{{ ShoppingDetails | json }}</pre>-->  
 
  
<table id="tblContainer" style='width: 99%;table-layout:fixed;'> 
    <tr *ngIf="AddItemsTable"> 
        <td> 
            <table style="background-color:#FFFFFF; border: dashed 3px #6D7B8D; padding: 5px;width: 99%;table-layout:fixed;" cellpadding="2" 
                   cellspacing="2"> 
                <tr style="height: 30px;  color:#ff0000 ;border: solid 1px #659EC7;"> 
                    <td width="40px"> </td> 
                    <td> 
                        <h2> <strong>Add Items to Cart</strong></h2> 
                    </td> 
 
                </tr> 
                <tr> 
                    <td width="40px"> </td> 
                    <td> 
                        <table> 
                            <tr> 
                               
                                <td> 
 
                                    <img src="{{Imagename}}" width="150" height="150" /> 
 
                                </td> 
                                <td width="30"></td> 
                                <td valign="top"> 
                                    <table style="color:#9F000F;font-size:large" cellpadding="4" cellspacing="6"> 
 
                                        <tr> 
                                            <td> 
                                                <b>Item code </b> 
                                            </td> 
 
                                            <td> 
                                                : {{ItemID}} 
                                            </td> 
 
                                        </tr> 
                                        <tr> 
                                            <td> 
                                                <b>   Item Name</b> 
                                            </td> 
 
                                            <td> 
                                                : {{ItemName}} 
                                            </td> 
 
                                        </tr> 
                                        <tr> 
                                            <td> 
                                                <b> Price  </b> 
                                            </td> 
 
                                            <td> 
                                                : {{ItemPrice}} 
                                            </td> 
 
                                        </tr> 
                                        <tr> 
                                            <td> 
                                                <b> Description </b> 
 
                                            </td> 
                                            <td> 
                                                : {{Descrip}} 
                                            </td> 
 
                                        </tr> 
                                        <tr> 
                                            <td align="center" colspan="2"> 
                                                <table> 
 
                                                    <tr> 
                                                        <td> 
                                                            <button (click)=showCart() style="background-color:#4c792d;color:#FFFFFF;font-size:large;width:200px"> 
                                                                Add to Cart 
                                                            </button>  
                                                             
 
                                                        </td> 
                                                        <td rowspan="2"><img src="{{cartImageUrl}}" /></td> 
                                                    </tr> 
 
                                                </table> 
                                            </td> 
                                        </tr> 
                                    </table> 
                                </td> 
                            </tr> 
                        </table> 
                    </td> 
                </tr> 
            </table> 
        </td> 
    </tr> 
    <tr> 
        <td><hr style="height: 1px;color: #123455;background-color: #d55500;border: none;color: #d55500;" /></td> 
    </tr> 
    <tr *ngIf="CartDetailsTable"> 
        <td> 
             
            <table width="100%"> 
                <tr> 
                    <td> 
                        <table style="background-color:#FFFFFF; border: dashed 3px #6D7B8D; padding: 5px;width: 100%;table-layout:fixed;" cellpadding="2" 
                               cellspacing="2"> 
                            <tr style="height: 30px;  color:#123455 ;border: solid 1px #659EC7;"> 
                                <td width="40px"> </td> 
                                <td width="60%"> 
                                    <h1> My Recent Orders Items <strong style="color:#0094ff"> ({{totalItem}})</strong></h1>  
                                </td> 
                                <td align="right"> 
                                    <button (click)=showItems() style="background-color:#0094ff;color:#FFFFFF;font-size:large;width:300px;height:50px; 
                              border-color:#a2aabe;border-style:dashed;border-width:2px;"> 
                                        Add More Items 
                                    </button> 
                                      
                                </td> 
                            </tr> 
                        </table> 
                        
                    </td> 
                </tr> 
                <tr> 
                    <td> 
                        <table style="background-color:#FFFFFF; border:solid 2px #6D7B8D;padding: 5px;width: 100%;table-layout:fixed;" cellpadding="2" cellspacing="2"> 
                            <tr style="height: 30px; background-color:#336699 ; color:#FFFFFF ;border: solid 1px #659EC7;"> 
                                <td width="30" align="center">No</td> 
                                <td width="80" align="center"> 
                                    <b>Image</b> 
                                </td> 
                                <td width="90" align="center" style="border: solid 1px #FFFFFF; padding: 5px;table-layout:fixed;cursor: pointer;"> 
                                    <b>Item Code</b> 
                                </td> 
                                <td width="140" align="center" style="border: solid 1px #FFFFFF; padding: 5px;table-layout:fixed;cursor: pointer;"> 
                                    <b>Item Name</b> 
                                </td> 
                                <td width="160" align="center" style="border: solid 1px #FFFFFF; padding: 5px;table-layout:fixed;cursor: pointer;"> 
                                    <b>Decription</b> 
                                </td> 
                                <td width="90" align="center" style="border: solid 1px #FFFFFF; padding: 5px;table-layout:fixed;cursor: pointer;"> 
                                    <b>Price</b> 
                                </td> 
                                <td width="90" align="center" style="border: solid 1px #FFFFFF; padding: 5px;table-layout:fixed;cursor: pointer;"> 
                                    <b>Quantity</b> 
                                </td> 
                                <td width="90" align="center" style="border: solid 1px #FFFFFF; padding: 5px;table-layout:fixed;cursor: pointer;"> 
                                    <b>Total Price</b> 
                                </td> 
                                <td></td> 
                            </tr> 
 
                            <tbody *ngFor="let detail of cartDetails ; let i = index"> 
 
                                <tr> 
                                    <td style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;" align="center"> 
                                        {{i+1}} 
 
                                    </td> 
                                    <td align="center" style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;"> 
                                        <span style="color:#9F000F" *ngIf!="getImagename(detail.CImage_Name)"> 
                                            <img src="{{ImageUrl}}" style="height:56px;width:56px"> 
                                        </span> 
                                    </td> 
                                    <td style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;"> 
                                        <span style="color:#9F000F"> 
                                            {{detail.CItem_ID}} 
                                        </span> 
                                    </td> 
 
                                    <td style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;"> 
                                        <span style="color:#9F000F"> 
                                            {{detail.CItem_Name}} 
                                        </span> 
                                    </td> 
 
                                    <td style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;"> 
                                        <span style="color:#9F000F"> 
                                            {{detail.CDescription}} 
                                        </span> 
                                    </td> 
 
                                    <td align="right" style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;"> 
                                        <span style="color:#9F000F"> 
                                            {{detail.CItem_Price  | number}} 
                                        </span> 
                                    </td> 
 
                                    <td style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;" align="right"> 
                                        <span style="color:#9F000F"> 
                                            {{detail.CQty}} 
                                        </span> 
                                    </td> 
 
                                    <td style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;" align="right"> 
                                        <span style="color:#9F000F"> 
                                            {{detail.CTotalPrice*detail.CQty  | number}} 
                                        </span> 
                                    </td> 
 
                                    <td align="center" style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;"> 
                                                  <button (click)=removeFromCart(i) style="background-color:#e11919;color:#FFFFFF;font-size:large;width:220px;height:40px;"> 
                                            Remove Item from Cart 
                                        </button> 
                                    </td> 
                                </tr> 
                            </tbody> 
                            <tr> 
                                <td colspan="5" height="40" align="right" > <strong>Total </strong></td> 
                                <td align="right" height="40"><strong>Price: {{ totalPrice | number}}</strong></td> 
                                <td align="right" height="40"><strong>Qty : {{ totalQty | number}}</strong></td> 
                                <td align="right" height="40"><strong>Sum: {{ GrandtotalPrice | number}}</strong></td> 
                                <td></td> 
                            </tr> 
                        </table> 
                    </td> 
                </tr> 
                 
            </table> 
        </td> 
    </tr> 
   
    <tr *ngIf="showDetailsTable"> 
 
        <td> 
            <table width="100%" style="background-color:#FFFFFF; border: dashed 3px #6D7B8D; padding: 5px;width: 100%;table-layout:fixed;" cellpadding="2" 
                               cellspacing="2"> 
                <tr> 
                    <td> 
                        <table style="background-color:#FFFFFF; border: dashed 3px #6D7B8D; padding: 5px;width: 100%;table-layout:fixed;" cellpadding="2" 
                               cellspacing="2"> 
                            <tr style="height: 30px;  color:#134018 ;border: solid 1px #659EC7;"> 
                                <td width="40px"> </td> 
                                <td width="60%"> 
                                    <h2> <strong>Item Details</strong></h2> 
                                </td> 
                                <td align="right"> 
                                    <button (click)=showShoppingItems() style="background-color:#d55500;color:#FFFFFF;font-size:large;width:300px;height:50px; 
                              border-color:#a2aabe;border-style:dashed;border-width:2px;"> 
                                        Show My Cart Items 
                                    </button> 
                                      
                                </td> 
                            </tr> 
                        </table> 
                    </td> 
                </tr> 
                
                <tr> 
                    <td> 
 
                        <table style="background-color:#FFFFFF; border: solid 2px #6D7B8D; padding: 5px;width: 100%;table-layout:fixed;" cellpadding="2" cellspacing="2" *ngIf="ShoppingDetails"> 
 
 
                            <tr style="height: 30px; background-color:#336699 ; color:#FFFFFF ;border: solid 1px #659EC7;"> 
                                <td width="40" align="center"> 
                                    <b>Image</b> 
                                </td> 
 
                                <td width="40" align="center" style="border: solid 1px #FFFFFF; padding: 5px;table-layout:fixed;cursor: pointer;"> 
                                    <b>Item Code</b> 
                                </td> 
 
                                <td width="120" align="center" style="border: solid 1px #FFFFFF; padding: 5px;table-layout:fixed;cursor: pointer;"> 
                                    <b>Item Name</b> 
                                </td> 
 
                                <td width="120" align="center" style="border: solid 1px #FFFFFF; padding: 5px;table-layout:fixed;cursor: pointer;"> 
                                    <b>Decription</b> 
                                </td> 
 
                                <td width="40" align="center" style="border: solid 1px #FFFFFF; padding: 5px;table-layout:fixed;cursor: pointer;"> 
                                    <b>Price</b> 
                                </td> 
 
                                <td width="90" align="center" style="border: solid 1px #FFFFFF; padding: 5px;table-layout:fixed;cursor: pointer;"> 
                                    <b>User Name</b> 
                                </td> 
 
                            </tr> 
                            <tr style="height: 30px; background-color:#336699 ; color:#FFFFFF ;border: solid 1px #659EC7;"> 
                                <td width="40" align="center"> 
                                    Filter By -> 
                                </td> 
 
                                <td width="200" colspan="5" style="border: solid 1px #FFFFFF; padding: 5px;table-layout:fixed;"> 
 
                                    Item Name : 
 
 
                                    <input type="text" (ngModel)="ItemName" (keyup)="getShoppingDetails(myInput.value)" #myInput style="background-color:#fefcfc;color:#334668;font-size:large; 
                                                   border-color:#a2aabe;border-style:dashed;border-width:2px;" /> 
                                </td> 
 
                            </tr> 
 
                            <tbody *ngFor="let detail of ShoppingDetails"> 
                                <tr> 
                                    <td align="center" style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;"> 
                                        <span style="color:#9F000F" *ngIf!="getImagename(detail.image_Name)"> 
                                            <img src="{{ImageUrl}}" style="height:56px;width:56px" (click)=showToCart(detail.item_ID,detail.item_Name,detail.item_Price,detail.image_Name,detail.description,detail.addedBy)> 
                                        </span> 
 
                                    </td> 
                                    <td style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;"> 
                                        <span style="color:#9F000F"> 
                                            {{detail.item_ID}} 
                                        </span> 
                                    </td> 
 
                                    <td style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;"> 
                                        <span style="color:#9F000F"> 
                                            {{detail.item_Name}} 
                                        </span> 
                                    </td> 
 
                                    <td style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;"> 
                                        <span style="color:#9F000F"> 
                                            {{detail.description}} 
                                        </span> 
                                    </td> 
 
                                    <td align="right" style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;"> 
                                        <span style="color:#9F000F"> 
                                            {{detail.item_Price}} 
                                        </span> 
                                    </td> 
 
 
                                    <td style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;"> 
                                        <span style="color:#9F000F"> 
                                            {{detail.addedBy}} 
                                        </span> 
                                    </td> 
                                </tr> 
                        </table> 
                    </td> 
                    </tr> 
                </table> 
              </td>    
             </tr> 
           </table> 


Build and run the application

Points of Interest

First create the Database and Table in your SQL Server. You can run the SQL Script from this article to create ShoppingDB database and ItemDetails Table and also don’t forget to change the connection string from “appsettings.json”.

LINK: https://www.codeproject.com/Articles/1168725/ASP-NET-Core-Angular-Shopping-Cart-Using-Web-API

ASP.NET MVC 5 với AngularJS - Phần 1


Giới thiệu
AngularJS theo cách tôi đã học, tôi đã có ý định chia sẻ với độc giả, những người đang đi tìm kiếm cho việc học AngularJS theo cách được rút gọn. Bài viết này là dành cho họ.
Dưới đây là luồng bài viết chúng ta sẽ đi lần lượt từng bước một. Trước tiên chúng ta sẽ lựa chọn với câu hỏi cái gì và tại sao.

  • Vậy AngularJS là gì?
  • Tại sao lại đặt tên là Angular?
  • Tại sao phải dùng một framework khác JavaScript? Jquery với Angular
  • Chúng ta sẽ so sánh sự khác biệt của chúng với một ví dụ
  • Tải về và cài đặt thư viện AngularJS trong Visual Studio 2015
  • Bắt đầu AngularJS với Visual Studio
  • Chúng ta sẽ đệ trình một form với AngularJS
  • Tìm hiểu về trạng thái Form
  • Gửi dữ liệu form đến MVC Controller
  • Tạo URL trong AngularJS

Ok, chúng ta hãy bắt đầu. Trước khi chúng ta tập trung vào bất kỳ chủ đề nào, chúng ta phải biết AngularJS là gì


AngularJS là gì
AngularJS là một framework JavaScript phía client dựa trên mẫu MVC. Nó là mã nguồn mở, được hỗ trợ và duy trì bởi Google. AngularJS còn gọi là "Angular" hay "Angular.js" đã được phát hành lần đầu vào năm 2009, mục đích để cải tiến quy trình phát triển và kiểm thử.

Tại sao lại đặt tên AngularJS
Chúng ta biết rằng HTML được chứa bên trong cặp dấu ngoặc nhọn (angle brackets - <>) (ví dụ: <html>) vì vậy tên Angular cũng đến từ ý nghĩa đó. AngularJS sử dụng các chỉ thị như ng-app, ng-model mà tiền tố với "ng" (chỉ dẫn cơ bản) làm chúng ta liên tưởng đến "Angular"

Tại sao phải dùng một framework khác JavaScript


Cả hai được dùng với mục đích tạo kịch bản phía Client, nhưng AngularJS đơn giản là mang đến nhiều tính năng và lợi ích hơn. Như chúng ta đã biết AngularJS là framework dựa trên mẫu MVC, đây là mẫu có tính chất module và có khả năng được sử dụng lại.
Dưới đây là tổng quan về cả hai:
AngularJS:

  • Là framework JavaScript MVC được hỗ trợ và duy trì bởi Google
  • Data-binding thông minh
  • Sử dụng mẫu thiết kế MVC
  • Hỗ trợ Form Validations
  • Hỗ trợ định tuyến (Single Page Application)
  • Sử dụng Dependency Injection(DI)
  • Unit test dễ dàng
  • Kiến trúc modular và tái sử dụng
  • REST-friendly

jQuery

  • Là framework JavaScript mã nguồn mở khá nhẹ
  • Là công cụ tuyệt vời cho việc tương tác và điều khiển các thành phần DOM

Ví dụ:
AngularJS

1
2
3
4
5
6
7
8
9
<body ng-app>
   First Name: <input type="text"ng-model="fname"/>
  
   Last Name: <input type="text"ng-model="lname"/>
  
   Result: {{fname+''+lname}}
</body>
</html>
<script src="Scripts/angular.min.js"></script>


jQuery

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<body>
   First Name: <inputtype="text"id="txtfName"/>
  
   Last Name: <inputtype="text"id="txtlName"/>
  
   Result: <labelid="lblName"></label>
</body>
</html>
<script src="Scripts/jquery-2.2.0.min.js"></script>
<script type="text/javascript">
   $(document).ready(function () {
       $(function () {
           $('#txtfName').keyup(function () {
               $('#lblName').text($('#txtfName').val() +' ' + $('#txtlName').val());
           });
 
           $('#txtlName').keyup(function () {
               $('#lblName').text($('#txtfName').val() +' ' + $('#txtlName').val());
           });
       });
   });
</script>


Bạn thích cái nào hơn? Cả hai đều cho ra cùng một kết quả
Ok, chúng ta hãy bắt đầu với AngularJS: trước tiên kiểm tra với một website đơn giản trong Visual Studio 2015

Tải và cài đặt thư viện AngularJS trong Visual Studio 2015
Truy cập vào website AngularJS và tải về


Nhấp chuột vào liên kết Tải về (Download) để tải phiên bản mới nhất của thư viện AngularJS.

AngularJS với Visual Studio
Hãy mở Visual Studio 2015 (IDE) lên, vào File -> New -> Project và sau đó một cửa sổ mới sẽ xuất hiện như hình bên dưới:

Hình 1.0
 
Nhấn chọn APS.NET Web Application, đổi tên ứng dụng, sau đó nhấn vào nút OK góc phải bên dưới, chọn Empty Template trong cửa sổ tiếp theo nhấn nút OK, Sẽ mất chút thời gian chờ đợi để chương trình nạp dự án trống.
Bây giờ điều đầu tiên chúng ta cần làm là đăng ký AngularJS.core trong ứng dụng này. Chúng ta cần phải có được tham chiếu từ Nuget
Để làm điều này chúng ta nhấn chuột phải lên tên dự án, nhấn vào Manager Nuget Packages như trong hình sau:
Hình 1.1
Trong cửa sổ tiếp theo lựa chọn tìm kiếm với tên "Angular", cài đặt phiên bản được cập nhật của AngularJS.core như hình sau
Hình 1.2
 
hoặc vào menu Tools -> NuGet Package Manager -> Package Manager Console, gõ vào lệnh Install-Package AngularJS.Core.
Tương tự chúng ta cũng cần thêm thư viện jQuery vào dự án của chúng ta như hình dưới
Hình 1.3
Các tiến trình cài đặt của chúng ta đã hoàn thành. Bây giờ kiểm tra nó với mã AngularJS trước đó của chúng ta so với phần jQuery.
Hãy thêm mới một trang HTML và đặt tên cho nó là "index"
Hình 1.4
Mã trong file index.html:
1
2
3
4
5
6
7
8
9
10
<body ng-app> First Name:  
   <input type="text" ng-model="fname" />  
    
 Last Name:  
   <input type="text" ng-model="lname" />  
    
 Result: {{fname+''+lname}} </body>  
   </html>  
   <script src="Scripts/angular.min.js">
</script>  

Chú ý rằng ví dụ trên là mã của một file HTML đơn giản, nhưng có một số thuộc tính mới chưa biết và dấu ngoặc ôm.
Các thuộc tính mới "ng-app", "ng-model" là các chỉ dẫn Angular và "{{}}" là biểu thức, sau đây chúng ta sẽ đi thảo luận về chúng.
Ồ, vậy chỉ dẫn AngularJS là gì? Các chỉ dẫn AngularJS là sự mở rộng các thuộc tính HTML với tiền tố "ng"
Để tìm hiểu nhiều hơn về các chỉ dẫn AngularJS, bấm vào đây

Kết quả


Form với AngularJS
Chúng ta hãy thêm một dự án MVC trống để làm việc với form và sau đó chúng ta sẽ gửi dữ liệu đến Controller. Để làm việc này bạn nhấn chuột phải lên solution đang tồn tại, nhấn File -> New -> Project và đặt tên cho nó là AngularJSForm

Hình 1.5

Bây giờ đăng ký thư viện AngularJS, xem lại Hình 1.1 - 1.3 ở trên.
Trong thư mục Controller thêm một class HomeController, và tạo một View tên là Index.cshtml

Hình 1.6

Chúng ta vào thư mục View -> Shared, sửa file _layout.cshtml, thêm "ng-app='myFormApp' vào thẻ body

1
<body ng-app="myFormApp">


Trong file Index.cshtml sửa như sau:
Form:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 <div id="content" ng-controller="CustomerController">
   <span ng-show="isViewLoading" class="viewLoading">
       <img src="~/Content/images/ng-loader.gif" /> loading...
   </span>
   <div ng-class="result">{{message}}</div>
   <hr />
   <form ng-submit="submitForm()" name="frmCustomer">
       <div>
           <labelfor="name">Customer Name</label>
           <input type="text" ng-model="cust.CustName" name="cname" placeholder="Enter your name" required ng-minlength="4" ng-maxlength="14" />
           <span class="error" ng-show="(frmCustomer.$dirty||submitted) && frmCustomer.cname.$error.required">Customer name is Required</span>
           <span class="error" ng-show="frmCustomer.$dirty && frmCustomer.cname.$error.minlength">Minimum length required is 5</span>
           <span class="error" ng-show="frmCustomer.$dirty && frmCustomer.cname.$error.maxlength">Maximum length required is 15</span>
       </div>
       <div>
           <labelfor="email">E-mail address</label>
           <input type="email" ng-model="cust.CustEmail" name="email" placeholder="Enter your Email" required />
           <span class="error" ng-show="(frmCustomer.$dirty ||submitted) && frmCustomer.email.$error.required">EmailId is Required!</span>
           <span class="error" ng-show="(frmCustomer.$dirty ||submitted) && frmCustomer.$error.email">Invalid EmailId!</span>
       </div>
       <div>
           <input type="submit" value="Submit" ng-disabled="frmCustomer.$invalid">
       </div>
   </form>
</div> 

Script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
@section JavaScript{
   <script src="~/Scripts/jquery-1.10.2.min.js"></script>
   <script src="~/Scripts/angular.min.js"></script>
   <script src="~/Scripts/angular-route.min.js"></script>
   <script>
           angular.module('myFormApp', []).
             controller('CustomerController',function ($scope, $http, $location, $window)              {
                $scope.cust = {};
                $scope.message ='';
                $scope.result ="color-default";
                $scope.isViewLoading =false;
 
                //get called when user submits the form
                $scope.submitForm =function () 
                                                    {
                   $scope.isViewLoading =true;
                   console.log('Form is submitted with:', $scope.cust);
 
                   //$http service that send or receive data from the remote server
                   $http(
                                                       {
                     method:'POST',
                     url:'/Home/CreateCustomer',data: $scope.cust
                   }).success(function (data, status, headers, config) 
                    {
                     $scope.errors = [];
                     if (data.success ===true
                                                    {
                         $scope.cust = {};
                         $scope.message ='Form data Submitted!';
                         $scope.result ="color-green";
                         $location.path(data.redirectUrl);
                         $window.location.reload();
                     }
                     else {
                         $scope.errors = data.errors;
                     }
                   }).error(function (data, status, headers, config) 
                                                       {
                       $scope.errors = [];
                       $scope.message ='Unexpected Error while saving data!!';
                   });
                   $scope.isViewLoading =false;
                 }
               }).config(function ($locationProvider) 
               {
 
                 //default = 'false'
                 $locationProvider.html5Mode(true);
               });
 
    </script>
}


Form style:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<style>
 
#content label {
   width:150px;
}
 
#content input[type=submit] {
   margin-left:154px;
   width:120px;
   padding:5px15px;
   background:#ff6a00;
   border:0none;
   cursor:pointer;
   color:#fff;
}
 
.error {
   color:red;
}
 
.color-default {
   color:#000;
}
 
.color-red {
   color:red;
}
 
.color-green {
   color:green;
}
 
#content input.ng-dirty.ng-invalid {
   border:1pxsolidred;
   background-color:#fff4f4;
}
 
</style>

Kết quả:

Giải thích code
Trong ví dụ về form của chúng ta có thêm một số thuộc tính mới "ng-app, ng-controller, ng-show, ng-class, ng-submit, ng-model, ng-disabled" chúng ta đã thấy "ng-model" được sử dụng trong ví dụ đầu tiên.
Đây là tất cả các chỉ dẫn của AngularJS
Chúng ta hãy thảo luận về điểm bắt đầu ứng dụng AngularJS, là Module. Vậy module trong AngularJS là gì?
Module: module không là gì cả nhưng là một container (khung chứa) các phần khác nhau của một ứng dụng cũng như là controller, service, filter, directives, factories, ...
Module xác định nơi ứng dụng cần được khởi động.

angular.module('myFormApp', [])

Đây là một phương thức module có hai tham số
Tham số đầu tiên là tên module, tham chiếu đến module "myFormApp" trong <body ng-app='myFormApp'>
Tham số thứ 2 là một mảng rỗng trong phương thức "angular.module(‘myFormApp’, [])". Mảng này là danh sách của các module phụ thuộc khác.

Tiếp theo chúng ta sẽ tập trung vào Javascript Controller (CustomerController)
Javascript Controller

1
2
3
.controller('CustomerController',function ($scope) {
   //inner code
});


Controller là một hàm Javascript trong AngularJS. Chỉ thị ng-controller trong <div id=”content” ng-controller=”CustomerController”>  chỉ định điều khiển ứng dụng
Sử dụng đối tượng$scope để điều khiển quyền kiểm soát hành vi của ứng dụng. Vậy thì, $scope là gì?
$scope: $scope là một "đối tượng" mà ở đó các phần tử DOM và controller "liên kết lại với nhau". Nói một cách đơn giản, $scope là cầu nối giữa HTML View và Javascript Controller
Vào đây để tìm hiểu thêm về $scope

HTML View:

1
<div ng-class="result">{{message}}</div>


Javascript Controller

1
2
3
.controller('CustomerController',function ($scope) {
   $scope.message ='Show in view';
})


Chúng ta đi thảo thuận về hợp lệ (validations) của form
Hợp lệ - Validations
Hợp lệ kiểm tra thông tin mà người sử dụng nhập vào có hợp lệ hay không. AngularJS cũng có tính năng hợp lệ dữ liệu giống như JQuery/JQueryUnobtrusive. Ở đây chúng ta sẽ tìm hiểu ngắn gọn về chúng.
Trường được yêu cầu hợp lệ (Required Field Validator): để hợp lệ kiểm tra dữ liệu người dùng nhập có rỗng hay không, với AngularJS chúng ta sử dụng thuộc tính HTML5 "required" hoặc "có thể sử dụng ng-required = "true"

1
<inputtype="email"ng-model="cust.CustEmail"name="email"required/>


Thông báo hợp lệ - Validation Message

1
2
3
<span class="error" ng-show="(frmCustomer.$dirty||submitted)&&
frmCustomer.email.$error.required">
EmailId is Required!</span>


Hợp lệ theo vùng - Range Validator: để kiểm tra dữ liệu đầu vào theo vùng với Angular chúng ta sử dụng các thuộc tính HTML5 "ng-minlength, ng-maxlength"

1
2
<inputtype="text" ng-model="cust.CustName" name="cname" requiredng-minlength="4"
 ng-maxlength="14"/>


Thông báo hợp lệ - Validation Message

1
2
3
4
5
<spanclass="error" ng-show="frmCustomer.$dirty&&
frmCustomer.cname.$error.minlength">Minimum length required is 5</span>
 
<spanclass="error" ng-show="frmCustomer.$dirty&&
frmCustomer.cname.$error.maxlength">Minimum length required is 15</span>


Kiểu hợp lệ - Type Validator: để kiểm tra kiểu email chúng ta có thể sử dụng hợp lệ này trong AngularJS

1
2
<spanclass="error" ng-show="(frmCustomer.$dirty||submitted)&&
frmCustomer.$error.email">Invalid EmailId!</span>  


Cập nhật trạng thái Form
Bản thân AngularJS có một số thuộc tính để cập nhật trạng thái form. Chúng là các giá trị true hay false

  • $error: Đối tượng chứa tất cả các thuộc tính hợp lệ áp dụng cho một phần tử cụ thể
  • $pristine: true nếu người dùng chưa tác động đến điều khiển, ngược lại trả về False
  • $valid: true nếu model hợp lệ
  • $invalid: true nếu model không hợp lệ
  • $dirty: true nếu người dùng đã thay đổi giá trị model ít nhất một lần 
  • $touched: true nếu người dùng đã chuyển hướng ra khỏi điều khiển
  • $untouched: true nếu người dùng chưa chuyển hướng ra khỏi điều khiển

Gửi dữ liệu Form đến MVC Controller
Để gửi form đến MVC Controller chúng ta cần thêm một phương thức vào HomeController và chúng ta cần sửa đổi CustomerController trong phần kịch bản - script.
Trong HomeController chúng ta thêm phương thức như sau:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[HttpPost]
public JsonResultCreateCustomer(Customer model)
{
   if (ModelState.IsValid)
   {
       //Data save to database
       returnJson(new
       {
           success =true
       });
   }
   return Json(new
   {
       success =false,
           errors = ModelState.Keys.
                      SelectMany(i => ModelState[i].Errors).
                      Select(m => m.ErrorMessage).ToArray()
   });
}


Tiếp đến sửa đổi Javascript trong CustomerController

1
2
3
4
5
6
7
angular.module('myFormApp', []).
controller('CustomerController',function ($scope, $http)
{
   $scope.cust = {};
   $scope.message ='';
   $scope.result ="color-default";
   $scope.isViewLoading =false
1
2
3
4
5
   //get called when user submits the form
   $scope.submitForm =function ()
   {
       $scope.isViewLoading =true;
       console.log('Form is submitted with:', $scope.cust); 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
       //$http service that send or receive data from the remote server
       $http(
       {
           method:'POST',
           url:'/Home/CreateCustomer',
           data: $scope.cust
       }).success(function (data, status, headers, config)
       {
           $scope.errors = [];
           if (data.success ===true)
           {
               $scope.cust = {};
               $scope.message ='Form data Submitted!';
               $scope.result ="color-green";
           }
           else
           {
               $scope.errors = data.errors;
           }
       }).error(function (data, status, headers, config)
       {
           $scope.errors = [];
           $scope.message ='Unexpected Error while saving data!!';
       });
       $scope.isViewLoading =false;
   }
});


Chúng ta hãy đặt một điểm ngắt - breakpoint ở phương thức CreateCustomer() trong HomeController và chạy nó, sau khi bạn gửi form nó sẽ dừng lại ở điểm ngắt - breakpoint.

Hình 1.7

Trong chế độ debug chúng ta có thể thấy model đã được ... với dữ liệu form mà chúng ta có thể gửi đến và lưu vào cơ sở dữ liệu.
Kết quả:

Kết quả tương tự như trước.

Giải thích code
Ở ví dụ về việc gửi dữ liệu form đến Controller ở trên chúng ra đã sử dụng dịch vụ (service) $http. Ồ vậy chúng là gì?

  • Service: Các dịch vụ (services) AngularJS là các hàm Javascript có mối quan hệ với controller, model hoặc các chỉ thị tùy chỉnh (custom directives). AngularJS cũng có các dịch vụ hữu ích khác như $interval, $window, $log. Để tìm hiểu nhiều hơn về các dịch vụ bấm vào đây
  • $http service: Chúng ta có thể sử dụng dịch vụ $http để gửi một yêu cầu AJAX. Trong ví dụ này, chúng ta đã gửi yêu cầu Http POST đến máy chủ từ xa để gửi dữ liệu.

Tạo URL HashTag(#) miễn phí trong AngularJS
Tiếp theo chúng ra sẽ chuyển hướng đến một URL mới sau khi form được gửi sử dụng dịch vụ $location, AngularJS sẽ thêm "#" vào url để ngăn chặn chuyển hướng đến một url mong muốn.
Tìm hiểu nhiều hơn về $locationProvide ở đây

Giải quyết vấn đề này bằng cách rút "#" ra khỏi URL, chúng ta cần Inject $locationProvider trong hàm config() của angular root module sau đó thiết lập html5Mode là true

1
2
3
.config(function ($locationProvider) {
   $locationProvider.html5Mode(true);
});


Trong phần script chúng ta cần sửa đổi CustomerController và thêm vào hai dòng code mà sẽ chỉ ra đường dẫn và chuyển hướng nạp lại toàn bộ trang

1
2
$location.path(data.redirectUrl);
$window.location.reload();


Thêm thẻ base trong phần head của master page/layout (_layout.cshtml) của ứng dụng

1
<basehref="/">

CustomerController(Javascript) đầy đủ:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
angular.module('myFormApp', []).
controller('CustomerController',function ($scope, $http, $location, $window)
{
   $scope.cust = {};
   $scope.message ='';
   $scope.result ="color-default";
   $scope.isViewLoading =false;
 
   //get called when user submits the form
   $scope.submitForm =function ()
   {
       $scope.isViewLoading =true;
       console.log('Form is submitted with:', $scope.cust);
 
       //$http service that send or receive data from the remote server
       $http(
       {
           method:'POST',
           url:'/Home/CreateCustomer',
           data: $scope.cust
       }).success(function (data, status, headers, config)
       {
           $scope.errors = [];
           if (data.success ===true)
           {
               $scope.cust = {};
               $scope.message ='Form data Submitted!';
               $scope.result ="color-green";
               $location.path(data.redirectUrl);
               $window.location.reload();
           }
           else
           {
               $scope.errors = data.errors;
           }
       }).error(function (data, status, headers, config)
       {
           $scope.errors = [];
           $scope.message ='Unexpected Error while saving data!!';
       });
       $scope.isViewLoading =false;
   }
}).config(function ($locationProvider)
{
   //default = 'false'
   $locationProvider.html5Mode(true);
});


HomeController(MVC) đầy đủ:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class HomeController: Controller
{
   // GET: Home
   publicActionResult Index()
   {
       return View();
   }
 
   [HttpPost]
 
   public JsonResultCreateCustomer(Customer model)
   {
       if (ModelState.IsValid)
       {
           //Data save to database
           varRedirectUrl = Url.Action("About","Home",new
           {
               area =""
           });
 
           returnJson(new
           {
               success =true, redirectUrl = RedirectUrl
           });
       }
 
       returnJson(new
       {
           success =false,
               errors = ModelState.Keys.
                            SelectMany(i => ModelState[i].Errors).
                            Select(m => m.ErrorMessage).ToArray()
       });
   }
 
   // GET: Home/About
   public ActionResult About()
   {
       return View();
   }
}



Kết quả

Nếu bạn quan tâm
Phần tiếp theo chúng ta sẽ tạo một ứng dụng mẫu với AngularJS để thực hiện CRUD với ASP.NET MVC.

Real-time applications using ASP.NET Core, SignalR & Angular

aspnet-core-signalr-angular

Blog post: Real-time applications using ASP.NET Core, SignalR & Angular

Features explained
  • Fire up an empty ASP.NET Core web application using yeoman
  • Configure and install MVC and SignalR Server dependencies
  • Install SignalR Client-Typescript dependencies
  • Create SignalR hubs
  • Integrate MVC Controllers (API) with SignalR
  • Create the Angular-SignalR service to communicate with SignalR hubs
  • Add Reccurent Tasks on a ASP.NET Core application

dotnet-core-api-14

Installation Instructions

  1. Clone or download the repository and open it on your favorite editor
  2. Make sure you have the latest .NET Core version installed (link 1 - link 2)
  3. Open a command prompt and run the following commands
    1. npm install
    2. bower install
    3. npm start

     

  4. Open another command prompt and run the following commands

     

    1. dotnet restore
    2. dotnet run

     

 

aspnet-core-signalr-angular

Microsoft Azure Deployment

Learn how to deploy an ASP.NET Core - Angular 2 - SignalR app on Microsoft Azure here.

Cross-platform Single Page Applications with ASP.NET Core 1.0, Angular 2 & TypeScript

Một ví dụ khá ngon cho SPA, đáng để tham khảo

ASP.NET Core, Angular 2 & TypeScript

Blog post:Cross-platform Single Page Applications using ASP.NET Core, Angular 2 and Typescript

SourceCode: aspnet5-angular2-typescript


aspnet5-agnular2-03

Frameworks - Tools - Libraries

  • ASP.NET Core
  • Entity Framework Core
  • Automapper
  • Angular 2
  • Typescript
  • Bootstrap 3
  • Gulp
  • Bower

Installation instructions - Part 1 (Applied for Windows/Linux/MAC)

    1. Install ASP.NET Core according to your development environment from here.
    2. Install NPM by installing Node.js.
    3. Install Bower, Gulp, Typescript and Typescript Definition Manager globally by typing the following commands on the console/terminal:
      • npm install -g bower
      • npm install -g gulp
      • npm install -g typescript
      • npm install -g typings
      • npm install -g tsd

Installation instructions - Part 2 (Run application in Visual Studio 2015, only for Windows users)

      1. Download and install Visual Studio 2015 from here.
      2. Open Visual Studio 2015 and install any update related to ASP.NET Core (check the notifications).
      3. Download the source code and open the solution.
      4. By the time you open the solution, VS 2015 will try to restore Nuget, NPM and Bower packages.
      5. In case it fails to restore NPM and Bower packages, open a console and navigate at the src/PhotoGallery path where the package.json and bower.json files exist. Run the following commands:
        • npm install
        • typings install
        • bower install
        • gulp build-spa
      6. Open appsettings.json file and alter the database connection string to reflect your SQL Server environment.
      7. Open a console and navigate to src/PhotoGallery where the project.json exists. Run the following commands to enable migrations and create the database:
        1. dotnet ef migrations add initial
        2. dotnet ef database update
      8. Build your application and run it. You can use username: chsakell and password: photogallery to sign in or register a new user.

Installation instructions - Part 2 (Run application in Visual Studio Code, recommended for Linux/MAC users)

      1. Download and install Visual Studio Code from here.
      2. Install the csharp extension from here
      3. Download the source code and open the src/PhotoGallery folder in Visual Studio Code.
      4. Open a console/terminal and navigate at the src/PhotoGallery path where the package.json and bower.json files exist. Run the following commands:
        • npm install
        • typings install
        • bower install
        • gulp build-spa
      5. Run the following command to restore Nuget Packages (dependencies)
        • dotnet restore
      6. Application uses SQL Server so in case you want to run the app in Linux or MAC simply set "InMemoryProvider": true in appsettings.json and skip to the last 3 steps to run the app.
      7. Open appsettings.json file and alter the database connection string to reflect your SQL Server environment.
      8. Open a console/terminal and navigate to src/PhotoGallery where the project.json exists. Run the following commands to enable migrations and create the database:
        1. dotnet ef migrations add initial
        2. dotnet ef database update
      9. Host your application using Kestrel by typing the following command while at src/PhotoGallery:
        • dotnet run
      10. Open a browser and navigate to http://localhost:5000/
      11. You can use username: chsakell and password: photogallery to sign in or register a new user.

Microsoft Azure Deployment

Learn how to deploy the PhotoGallery app on Microsoft Azure here.