65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 ASP.NET CORE 2 和 Angular 4、EntityFramework Core、primeng 组件和 toastr-ng2 进行 CRUD 操作

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.67/5 (30投票s)

2017 年 7 月 24 日

CPOL

5分钟阅读

viewsIcon

80083

downloadIcon

3522

使用 ASP.NET CORE 2 和 Angular 4、EntityFramework Core、primeng 组件和 toastr-ng2 进行 CRUD 操作

引言

在本文中,我将创建一个 ASP.NET Core 2.0 应用程序。在这里,我将向您展示如何在 Visual Studio 2017 Preview 1 中使用 entity framework core 和 primeng 组件构建 Angular4 应用程序。

必备组件

请确保您已在计算机上安装了所有先决条件。如果没有,请逐一下载并安装所有软件。

首先,从此 链接下载并安装 Visual Studio 2017 Preview 1。

下载并安装 NET Core 2.0 SDK

使用 Visual Studio 2017 Preview 1 创建新的 Angular4Core2 应用程序

打开 VS 2017 并使用新的 .NET Core 模板创建新项目(请参见以下屏幕截图)。

用户单击上面的“确定”按钮后,将打开以下新窗口。

在这里,我们需要从高亮的下拉列表中选择“ASP.NET Core 2.0”和 Angular 模板,以创建 ASP.NET Core 2.0 应用程序与 Angular 4。

查看新的 ASP.NET Core 2.0 应用程序与 Angular 4 的结构。它会创建一个名为“ClientApp”的新文件夹,其中包含实际的 Angular 4 项目,以及“wwwroot”,这是一个特殊文件夹,用于存放我们所有实时 Web 文件。

只需清理并生成应用程序,它将还原所有相关的依赖项。(请参见以下屏幕截图。)

我们可以在此 Web 应用程序中使用类库项目。首先,您需要创建两个 .NET Core 库项目 - 一个用于业务逻辑,另一个用于数据访问层。

按照相同的步骤创建数据访问层库项目。最后,我们的项目将如下所示

在这里,我将使用数据库优先的方法使用 Entity Framework Core。要使用此方法,我们需要在 SQL Server 中创建一个示例数据库表。请在您的 SQL Server 中运行以下脚本

USE [master]
GO
/****** Object:  Database [ContactDB]    Script Date: 07/23/2017 21:48:54 ******/
CREATE DATABASE [ContactDB]
 CONTAINMENT = NONE
 ON  PRIMARY
( NAME = N'ContactDB', _
FILENAME = N'C:\Program Files (x86)\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\ContactDB.mdf',_
 SIZE = 5120KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
 LOG ON
( NAME = N'ContactDB_log', _
FILENAME = N'C:\Program Files _
(x86)\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\ContactDB_log.ldf' , _
SIZE = 2048KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
GO
ALTER DATABASE [ContactDB] SET COMPATIBILITY_LEVEL = 110
GO
IF (1 = FULLTEXTSERVICEPROPERTY('IsFullTextInstalled'))
begin
EXEC [ContactDB].[dbo].[sp_fulltext_database] @action = 'enable'
end
GO
ALTER DATABASE [ContactDB] SET ANSI_NULL_DEFAULT OFF
GO
ALTER DATABASE [ContactDB] SET ANSI_NULLS OFF
GO
ALTER DATABASE [ContactDB] SET ANSI_PADDING OFF
GO
ALTER DATABASE [ContactDB] SET ANSI_WARNINGS OFF
GO
ALTER DATABASE [ContactDB] SET ARITHABORT OFF
GO
ALTER DATABASE [ContactDB] SET AUTO_CLOSE OFF
GO
ALTER DATABASE [ContactDB] SET AUTO_SHRINK OFF
GO
ALTER DATABASE [ContactDB] SET AUTO_UPDATE_STATISTICS ON
GO
ALTER DATABASE [ContactDB] SET CURSOR_CLOSE_ON_COMMIT OFF
GO
ALTER DATABASE [ContactDB] SET CURSOR_DEFAULT  GLOBAL
GO
ALTER DATABASE [ContactDB] SET CONCAT_NULL_YIELDS_NULL OFF
GO
ALTER DATABASE [ContactDB] SET NUMERIC_ROUNDABORT OFF
GO
ALTER DATABASE [ContactDB] SET QUOTED_IDENTIFIER OFF
GO
ALTER DATABASE [ContactDB] SET RECURSIVE_TRIGGERS OFF
GO
ALTER DATABASE [ContactDB] SET  DISABLE_BROKER
GO
ALTER DATABASE [ContactDB] SET AUTO_UPDATE_STATISTICS_ASYNC OFF
GO
ALTER DATABASE [ContactDB] SET DATE_CORRELATION_OPTIMIZATION OFF
GO
ALTER DATABASE [ContactDB] SET TRUSTWORTHY OFF
GO
ALTER DATABASE [ContactDB] SET ALLOW_SNAPSHOT_ISOLATION OFF
GO
ALTER DATABASE [ContactDB] SET PARAMETERIZATION SIMPLE
GO
ALTER DATABASE [ContactDB] SET READ_COMMITTED_SNAPSHOT OFF
GO
ALTER DATABASE [ContactDB] SET HONOR_BROKER_PRIORITY OFF
GO
ALTER DATABASE [ContactDB] SET RECOVERY FULL
GO
ALTER DATABASE [ContactDB] SET  MULTI_USER
GO
ALTER DATABASE [ContactDB] SET PAGE_VERIFY CHECKSUM  
GO
ALTER DATABASE [ContactDB] SET DB_CHAINING OFF
GO
ALTER DATABASE [ContactDB] SET FILESTREAM( NON_TRANSACTED_ACCESS = OFF )
GO
ALTER DATABASE [ContactDB] SET TARGET_RECOVERY_TIME = 0 SECONDS
GO
USE [ContactDB]
GO
/****** Object:  Table [dbo].[Contacts]    Script Date: 07/23/2017 21:48:54 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Contacts](
    [ContactId] [int] IDENTITY(1,1) NOT NULL,
    [Email] [varchar](50) NULL,
    [FirstName] [varchar](50) NULL,
    [LastName] [varchar](50) NULL,
    [Phone] [varchar](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
SET ANSI_PADDING OFF
GO
USE [master]
GO
ALTER DATABASE [ContactDB] SET  READ_WRITE
GO

现在我们可以使用上述现有数据库生成模型。但在此之前,我们需要使用程序包管理器控制台在我们的数据访问类库项目中安装以下程序包。

  1. Microsoft.EntityFrameworkCore.Tools
  2. Microsoft.EntityFrameworkCore.Design
  3. Microsoft.EntityFrameworkCore.SqlServer.Design

在我们的数据访问库项目中运行以下命令,以从现有数据库创建模型(请参见以下屏幕截图)

有关从现有数据库创建模型的更多详细信息,请参阅以下链接

上述命令成功执行后,将在我们的数据访问层项目中创建一个名为“Models”的文件夹,其中包含数据库实体。(请参见以下屏幕截图。)

ContactDBContext.cs 类

using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;

namespace DataAccessLibrary.Models
{
    public partial class ContactDBContext : DbContext
    {
        public virtual DbSet<Contacts> Contacts { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
               // #warning To protect potentially sensitive information in your connection string, you should move it out of source code. See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings.
                optionsBuilder.UseSqlServer(@"Server=yourservername;Database=ContactDB;User Id=youruser;Password=yourpassword;Trusted_Connection=True;");
            }
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Contacts>(entity =>
            {
                entity.HasKey(e => e.ContactId);

                entity.Property(e => e.Email)
                    .HasMaxLength(50)
                    .IsUnicode(false);

                entity.Property(e => e.FirstName)
                    .HasMaxLength(50)
                    .IsUnicode(false);

                entity.Property(e => e.LastName)
                    .HasMaxLength(50)
                    .IsUnicode(false);

                entity.Property(e => e.Phone)
                    .HasMaxLength(50)
                    .IsUnicode(false);
            });
        }
    }
}

Contacts.cs

using System;

namespace DataAccessLibrary.Models
{
    public partial class Contacts
    {
        public int ContactId { get; set; }
        public string Email { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Phone { get; set; }
    }
}

现在,我们的数据访问层已完成。现在,将您的数据访问引用添加到业务层项目中,并将您的业务层引用添加到您的 Web 项目中。

现在,让我们开始在业务层库项目中创建一个用于 CRUD 操作的存储库类。

在业务层项目内创建一个新文件夹(例如,“Repository”),并在该文件夹内创建一个接口(例如,“IContactRepository.cs”)和一个类(例如,“ContactRepository”),其中包含用于 CRUD 操作的几个方法。

IContactRepository.cs

using BusinessLibrary.Model;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace BusinessLibrary
{
    public interface IContactRepository
    {
        Task<List<Contact>> GetAllContact();
        Task<bool> SaveContact(Contact model);
        Task<bool> DeleteContactByID(int id);
    }
}

using DataAccessLibrary.Models;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using BusinessLibrary.Model;
using System.Linq;

namespace BusinessLibrary
{
    public class ContactRepository : IContactRepository
    {
        public async Task<bool> DeleteContactByID(int id)
        {
            using (ContactDBContext db = new ContactDBContext())
            {

                Contacts contact = db.Contacts.Where(x => x.ContactId == id).FirstOrDefault();
                if (contact != null)
                {
                    db.Contacts.Remove(contact);
                }
                return await db.SaveChangesAsync() >= 1;
            }
        }

        public async Task<List<Contact>> GetAllContact()
        {
            using (ContactDBContext db = new ContactDBContext())
            {
                return await (from a in db.Contacts
                              select new Contact
                              {
                                  ContactId = a.ContactId,
                                  FirstName = a.FirstName,
                                  LastName = a.LastName,
                                  Email = a.Email,
                                  Phone = a.Phone
                              }).ToListAsync();
            }
        }

        public async Task<bool> SaveContact(Contact model)
        {
            using (ContactDBContext db = new ContactDBContext())
            {
                Contacts contact = db.Contacts.Where
                        (x => x.ContactId == model.ContactId).FirstOrDefault();
                if (contact == null)
                {
                    contact = new Contacts()
                    {
                        FirstName = model.FirstName,
                        LastName = model.LastName,
                        Email = model.Email,
                        Phone = model.Phone
                    };
                    db.Contacts.Add(contact);

                }
                else
                {
                    contact.FirstName = model.FirstName;
                    contact.LastName = model.LastName;
                    contact.Email = model.Email;
                    contact.Phone = model.Phone;
                }

                return await db.SaveChangesAsync() >= 1;
            }
        }
    }
}

我们的业务层项目已完成。现在,我们需要将上述存储库注册到我们 Web 项目的 startup.cs 类中。

Startup.cs 类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.SpaServices.Webpack;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using BusinessLibrary;

namespace Angular4Core2
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            services.AddTransient<IContactRepository, ContactRepository>();
        }

        // This method gets called by the runtime. 
        // Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
                {
                    HotModuleReplacement = true
                });
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");

                routes.MapSpaFallbackRoute(
                    name: "spa-fallback",
                    defaults: new { controller = "Home", action = "Index" });
            });
        }
    }
}

我添加了 ContactController 类,并将我们的存储库作为依赖项注入,以便我们可以使用存储库执行 CRUD 操作。

ContactController.cs 类

using BusinessLibrary;
using BusinessLibrary.Model;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;

namespace Angular4Core2.Controllers
{
    public class ContactController : Controller
    {
        public IContactRepository ContactRepo;

        public ContactController(IContactRepository contactRepo)
        {
            ContactRepo = contactRepo;
        }

        [HttpGet, Produces("application/json")]
        public async Task<IActionResult> GetContacts()
        {
            var data = await ContactRepo.GetAllContact();
            return Json(new { result = data });
        }

        [HttpPost, Produces("application/json")]
        public async Task<IActionResult> SaveContact([FromBody] Contact model)
        {
            return Json(await ContactRepo.SaveContact(model));
        }

        [HttpDelete]
        public async Task<IActionResult> DeleteContactByID(int id)
        {
            return Json(await ContactRepo.DeleteContactByID(id));
        }

    }
}

现在,我们需要修改“package.json”文件,添加以下依赖项。

package.json

{
  "name": "Angular4Core2",
  "version": "0.0.0",
  "scripts": {
    "test": "karma start ClientApp/test/karma.conf.js"
  },
  "dependencies": {
    "@angular/animations": "4.1.2",
    "@angular/common": "4.1.2",
    "@angular/compiler": "4.1.2",
    "@angular/core": "4.1.2",
    "@angular/forms": "4.1.2",
    "@angular/http": "4.1.2",
    "@angular/platform-browser": "4.1.2",
    "@angular/platform-browser-dynamic": "4.1.2",
    "@angular/platform-server": "4.1.2",
    "@angular/router": "4.1.2",
    "@types/node": "7.0.18",
    "angular2-template-loader": "0.6.2",
    "aspnet-prerendering": "^2.0.5",
    "aspnet-webpack": "^1.0.29",
    "awesome-typescript-loader": "3.1.3",
    "bootstrap": "3.3.7",
    "css": "2.2.1",
    "css-loader": "0.28.1",
    "es6-shim": "0.35.3",
    "event-source-polyfill": "0.0.9",
    "expose-loader": "0.7.3",
    "extract-text-webpack-plugin": "2.1.0",
    "file-loader": "0.11.1",
    "html-loader": "0.4.5",
    "isomorphic-fetch": "2.2.1",
    "jquery": "3.2.1",
    "json-loader": "0.5.4",
    "preboot": "4.5.2",
    "raw-loader": "0.5.1",
    "reflect-metadata": "0.1.10",
    "rxjs": "5.4.0",
    "style-loader": "0.17.0",
    "to-string-loader": "1.1.5",
    "typescript": "2.3.2",
    "url-loader": "0.5.8",
    "webpack": "2.5.1",
    "webpack-hot-middleware": "2.18.0",
    "webpack-merge": "4.1.0",
    "zone.js": "0.8.10",
    "primeng": "1.0.0",
    "toastr-ng2": "4.1.1"
  },
  "devDependencies": {
    "@types/chai": "3.5.2",
    "@types/jasmine": "2.5.47",
    "chai": "3.5.0",
    "jasmine-core": "2.6.1",
    "karma": "1.7.0",
    "karma-chai": "0.1.0",
    "karma-chrome-launcher": "2.1.1",
    "karma-cli": "1.0.1",
    "karma-jasmine": "1.1.0",
    "karma-webpack": "2.0.3"
  }
}

PrimeNG 组件

在上面的 package.json 文件中,我们正在使用 primeng 组件(例如用于以表格格式显示数据的 datatable),它是一组丰富的 UI 组件,并且是开源组件。请参阅以下链接以获取更多详细信息

toastr-ng2 NPM

我们还使用 toastr-ng2 包来显示特定 CRUD 操作的 toast 消息。请参考以下链接以获取其他功能和安装步骤

Angular 4

现在,让我们开始在我们的应用程序中使用 Angular 4 创建客户端应用程序。

在这里,我在我们的 app 文件夹内创建了一个客户端模型,其中包含与我们在上一节中定义的服务器端模型对应的属性。

contact.ts:

export interface Contact {
    contactId?;
    firstName?;
    lastName?;
    email?;
    phone?;
}

index.ts:

export * from './contact';

下一步是创建一个客户端服务,该服务通过 Angular Http client 提供客户端和服务器之间的数据传输功能。

contact.service.ts:

import { Injectable } from '@angular/core';
import { Http, Response, Headers, RequestOptions } from '@angular/http';
import { Contact } from '../_models/index';
import { Observable } from 'rxjs/Observable';
import "rxjs/Rx";

@Injectable()
export class ContactService {

    private _getContactsUrl = "/Contact/GetContacts";
    public _saveUrl: string = '/Contact/SaveContact/';
    public _updateUrl: string = '/Contact/UpdateContact/';
    public _deleteByIdUrl: string = '/Contact/DeleteContactByID/';

    constructor(private http: Http) { }

    getContacts() {
        var headers = new Headers();
        headers.append("If-Modified-Since", "Tue, 24 July 2017 00:00:00 GMT");
        var getContactsUrl = this._getContactsUrl;
        return this.http.get(getContactsUrl, { headers: headers })
            .map(response => <any>(<Response>response).json());
    }

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

        return this.http.post(this._saveUrl, body, options)
            .map(res => res.json().message)
            .catch(this.handleError);
    }

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

        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');
    }

}

index.ts:

export * from './contact.service';

现在,我们需要定义我们的 contact 组件及其视图详细信息,它负责处理我们应用程序中的所有 CRUD 操作。

contact.component.ts:

import { Component, OnInit } from '@angular/core';
import { Contact } from '../../_models/index';
import { ContactService } from '../../_services/index';
import { ToastrService } from 'toastr-ng2';
import { InputTextModule, DataTableModule, ButtonModule, DialogModule } from 'primeng/primeng';

class ContactInfo implements Contact {
    constructor(public contactId?, public firstName?, public lastName?, public email?, public phone?) { }
}

@Component({
    selector: 'contact',
    templateUrl: './contact.component.html'
})
export class ContactComponent implements OnInit {

    private rowData: any[];
    displayDialog: boolean;
    displayDeleteDialog: boolean;
    newContact: boolean;
    contact: Contact = new ContactInfo();
    contacts: Contact[];
    public editContactId: any;
    public fullname: string;

    constructor(private contactService: ContactService, private toastrService: ToastrService) {

    }

    ngOnInit() {
        this.editContactId = 0;
        this.loadData();
    }

    loadData() {
        this.contactService.getContacts()
            .subscribe(res => {
                this.rowData = res.result;
            });
    }

    showDialogToAdd() {
        this.newContact = true;
        this.editContactId = 0;
        this.contact = new ContactInfo();
        this.displayDialog = true;
    }


    showDialogToEdit(contact: Contact) {
        this.newContact = false;
        this.contact = new ContactInfo();
        this.contact.contactId = contact.contactId;
        this.contact.firstName = contact.firstName;
        this.contact.lastName = contact.lastName;
        this.contact.email = contact.email;
        this.contact.phone = contact.phone;
        this.displayDialog = true;
    }

    onRowSelect(event) {
    }

    save() {
        this.contactService.saveContact(this.contact)
            .subscribe(response => {
                this.contact.contactId > 0 ? this.toastrService.success('Data updated Successfully') :
                    this.toastrService.success('Data inserted Successfully');
                this.loadData();
            });
        this.displayDialog = false;
    }

    cancel() {
        this.contact = new ContactInfo();
        this.displayDialog = false;
    }


    showDialogToDelete(contact: Contact) {
        this.fullname = contact.firstName + ' ' + contact.lastName;
        this.editContactId = contact.contactId;
        this.displayDeleteDialog = true;
    }

    okDelete(isDeleteConfirm: boolean) {
        if (isDeleteConfirm) {
            this.contactService.deleteContact(this.editContactId)
                .subscribe(response => {
                    this.editContactId = 0;
                    this.loadData();
                });
            this.toastrService.error('Data Deleted Successfully');
        }
        this.displayDeleteDialog = false;
    }
}

contact.component.html (其中包含 primeng 组件)

<table style="width:80%;margin-left: 100px">
    <tr>
        <td>
           <h2>Contact Details</h2>
        </td>
    </tr>
    <tr>
        <td>
            <button type="button" pButton icon="fa-plus" 
             style="float:left" (click)="showDialogToAdd()" label="Add"></button>
        </td>
    </tr>
    <tr>
        <td>
            <br />
            <div class="ContentSideSections Implementation">
                <p-dataTable [value]="rowData"  [rows]="10" [paginator]="true" 
                         [pageLinks]="3" [rowsPerPageOptions]="[5,10,20]">
                    <header>Contact Details</header>
                    <p-column field="contactId" [style]="{'width':'50px'}" 
                       header="ID" [sortable]="true"></p-column>
                    <p-column field="firstName" 
                    header="FirstName" [sortable]="true"></p-column>
                    <p-column field="lastName" 
                    header="LastName" [sortable]="true"></p-column>
                    <p-column field="email" [style]="{'width':'200px'}" 
                           header="Email" [sortable]="true"></p-column>
                    <p-column field="phone" 
                    header="Phone No" [sortable]="true"></p-column>
                    <p-column header="Edit">
                        <ng-template let-col let-contact="rowData" 
                        pTemplate type="body">
                            <button type="button" pButton icon="fa-check" 
                              (click)="showDialogToEdit(contact)" 
                              label="Edit"></button>
                        </ng-template>
                    </p-column>
                    <p-column header="Delete">
                        <ng-template let-col let-contact="rowData" 
                        pTemplate type="body">
                            <button type="button" pButton icon="fa-close" 
                             (click)="showDialogToDelete(contact)" 
                             label="Delete"></button>
                        </ng-template>
                    </p-column>
                    <footer><div class="ui-helper-clearfix" 
                    style="width:100%"></div></footer>
                </p-dataTable>

                <p-dialog header="Contact Details" [(visible)]="displayDialog" 
                             [responsive]="true" 
                             showEffect="fade" [modal]="true">
                    <div class="ui-grid ui-grid-responsive ui-fluid ui-grid-pad">
                        <div class="ui-grid-row">
                            <div class="ui-grid-col-4"><label 
                            for="firstname">FirstName</label></div>
                            <div class="ui-grid-col-8"><input pInputText id="vin" 
                                           [(ngModel)]="contact.firstName" /></div>
                        </div>
                        <div class="ui-grid-row">
                            <div class="ui-grid-col-4"><label 
                            for="lastname">LastName</label></div>
                            <div class="ui-grid-col-8"><input pInputText id="lastname" 
                                   [(ngModel)]="contact.lastName" /></div>
                        </div>
                        <div class="ui-grid-row">
                            <div class="ui-grid-col-4"><label 
                            for="email">Email</label></div>
                            <div class="ui-grid-col-8"><input type="email" 
                                 pInputText id="email" [(ngModel)]="contact.email" /></div>
                        </div>
                        <div class="ui-grid-row">
                            <div class="ui-grid-col-4"><label 
                            for="mobile">Phone</label></div>
                            <div class="ui-grid-col-8"><input pInputText id="mobile" 
                                    [(ngModel)]="contact.phone" /></div>
                        </div>
                    </div>
                    <footer>
                        <div class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix">
                            <button type="button" pButton icon="fa-close" 
                                   (click)="cancel()" 
                                   label="Cancel"></button>
                            <button type="button" pButton icon="fa-check" 
                                   (click)="save()" *ngIf="newContact" 
                                   label="Save"></button>
                            <button type="button" pButton icon="fa-check" 
                                   (click)="save()" *ngIf="!newContact" 
                                   label="Update"></button>
                        </div>
                    </footer>
                </p-dialog>
                <p-dialog header="Confirm Deletion" [(visible)]="displayDeleteDialog" 
                                     modal="modal" showEffect="fade">
                    <p>
                        Are you sure to delete the following contact?
                    </p>
                    <p>
                        <strong>{{ fullname }}</strong><br />
                    </p>
                    <footer>
                        <div class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix">
                            <button type="button" pButton icon="fa-close" 
                                     (click)="okDelete(false)" label="No"></button>
                            <button type="button" pButton icon="fa-check" 
                                     (click)="okDelete(true)" label="Yes"></button>
                        </div>
                    </footer>
                </p-dialog>
            </div>
        </td>
    </tr>
</table>

应用程序模块文件。

现在,我们需要修改我们的应用程序模块文件(即“app.module.shared.ts”),该文件用于组织和引导我们的 Angular 4 应用程序。

app.module.shared.ts:

import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { RouterModule } from '@angular/router';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { Headers, RequestOptions, BaseRequestOptions } from '@angular/http';
import { APP_BASE_HREF, CommonModule, Location, LocationStrategy, HashLocationStrategy } 
             from '@angular/common';
// third party module to display toast
import { ToastrModule } from 'toastr-ng2';
//PRIMENG - Third party module
import { InputTextModule, DataTableModule, ButtonModule, DialogModule } from 'primeng/primeng';

import { AppComponent } from './components/app/app.component';
import { NavMenuComponent } from './components/navmenu/navmenu.component';
import { ContactComponent } from './components/contact/contact.component';

import { ContactService } from './_services/index';

class AppBaseRequestOptions extends BaseRequestOptions {
    headers: Headers = new Headers();
    constructor() {
        super();
        this.headers.append('Content-Type', 'application/json');
        this.body = '';
    }
}

@NgModule({
    declarations: [
        AppComponent,
        NavMenuComponent,
        ContactComponent
    ],
    providers: [ContactService,
        { provide: LocationStrategy, useClass: HashLocationStrategy },
        { provide: RequestOptions, useClass: AppBaseRequestOptions }],
    imports: [
        CommonModule,
        HttpModule,
        FormsModule,
        BrowserAnimationsModule,
        ToastrModule.forRoot(),
        InputTextModule, DataTableModule, ButtonModule, DialogModule,
        RouterModule.forRoot([
            { path: '', redirectTo: 'contact', pathMatch: 'full' },
            { path: 'contact', component: ContactComponent },
            { path: '**', redirectTo: 'contact' }
        ])
    ]
})
export class AppModuleShared {
}

我稍微修改了此应用程序的导航模板,如下所示

navmenu.component.html

<div class='main-nav'>
    <div class='navbar navbar-inverse'>
        <div class='navbar-header'>
            <button type='button' class='navbar-toggle' data-toggle='collapse' 
                                  data-target='.navbar-collapse'>
                <span class='sr-only'>Toggle navigation</span>
                <span class='icon-bar'></span>
                <span class='icon-bar'></span>
                <span class='icon-bar'></span>
            </button>
            <a class='navbar-brand' [routerLink]="['/contact']">Angular4Core2</a>
        </div>
        <div class='clearfix'></div>
        <div class='navbar-collapse collapse'>
            <ul class='nav navbar-nav'>
                <li [routerLinkActive]="['link-active']">
                    <a [routerLink]="['/contact']">
                        <span class='glyphicon glyphicon-home'></span> Contact
                    </a>
                </li>
            </ul>
        </div>
    </div>
</div>

就是这样。现在我们可以使用 IIS Express 运行我们的应用程序了。

让我们首先通过单击“添加”按钮创建一个新的联系人。

当我们在“添加”按钮上单击时,将显示以下模型弹出窗口,其中包含相关字段以及保存和取消按钮。

当我们在“保存”按钮上单击时,信息将成功保存到数据库,并向用户显示成功的 toast 消息。

让我们在上面的网格中使用“编辑”按钮更新上述信息。当我们单击编辑按钮时,将出现相同的模型对话框,其中包含已保存的信息。在这里,我稍微更改了一些信息,例如电子邮件和电话详细信息,然后单击更新按钮。

它将显示更新后的信息和更新的 toast 消息(请参见以下屏幕截图)

对于删除操作,我们在网格中有一个“删除”按钮。当我们单击删除按钮时,将出现一个确认对话框,供用户选择是/否选项。(请参见以下屏幕截图。)

当我们单击“是”按钮时,信息将从数据库中删除,并向用户显示一个删除 toast。(请参见以下屏幕截图。)

就是这样!我们已经完成了使用 ASP.NET Core 2 和 Angular 4 的 CRUD 操作。

希望您喜欢这篇文章。

© . All rights reserved.