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

.NET CORE 1.0, ANGULAR V2, WEBAPI 上的 CRUD 操作

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.94/5 (26投票s)

2016 年 8 月 12 日

CPOL

7分钟阅读

viewsIcon

64068

downloadIcon

3164

在上一篇文章中,我们了解了如何开始使用 .Net Core。在本文中,我们将根据之前的概念,查看与之前示例应用程序相关的数据库操作。

如果您是 .Net Core 新手,请阅读有关 .Net Core Startup 的上一篇文章。

在本文中,我们将探讨:

  1. 创建数据库
  2. 使用 Entity Framework Core(数据库优先方法),
    1. EF Core 概述
    2. 安装 Entity Framework
    3. 创建模型
    4. 配置 EF 服务
  3. 使用 MVC 6
    1. MVC6 概述
    2. 使用 WebAPI
  4. 使用 Angular V2
    1. 组件,
    2. 路线
    3. Service
  5. 配置服务器
    1. 在 IIS 内部/外部运行应用程序

让我们一步一步开始吧。

创建数据库 在开始使用 IDE 之前,让我们使用 SSMS2014 创建一个新数据库。将其命名为 PhoneBook。

创建一个名为 Contacts 的表,复制并运行以下脚本在 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

让我们开始吧。遵循我们之前的主题,我将使用之前的示例应用程序,用 Visual Studio 2015 打开它。

core_crud_1

它将自动开始恢复依赖项。生成并运行它。应用程序运行正常。

安装 Entity Framework:在安装之前,让我们先了解一下 EF Core 的新功能。

  • 建模: 这包括基本建模、数据注释、关系等。
  • 更改跟踪: 这包括访问跟踪状态、快照、通知更改跟踪。
  • SaveChanges: 这包括基本的保存功能、异步 SaveChanges、事务。
  • 查询: 这包括基本的 LINQ 支持、异步查询、原始 SQL 查询。
  • 数据库架构管理: 这包括数据库创建/删除 API、关系数据库迁移以及从数据库反向工程。
  • 数据库提供程序: 这包括 EntityFramework.SqlServer、Sqlite、InMemory。
  • 平台: 支持通用 Windows 平台 (UWP)、.NET Core、完整 .NET。

有关 EF Core 的更多详细信息,请访问 EF Core。让我们在我们的示例应用程序解决方案中为实体模型添加文件夹。core_crud_3

DbEntities:用于模型实体。EF 的安装非常简单。打开 project.json 文件,在 tools 部分指向,并用以下行修改该部分。

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

core_crud_4

修改后保存更改。

core_crud_5

包将自动恢复。让我们来解释一下它们是什么。

EntityFrameworkCore.SqlServer:数据库提供程序,它允许 Entity Framework Core 与 Microsoft SQL Server 一起使用。

EntityFrameworkCore.Tools:EF Core 的命令行工具。包含命令。

对于包管理器控制台

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

对于命令窗口

  • dotnet ef dbcontext scaffold

我们将看到如何使用这两个命令。EntityFrameworkCore.SqlServer.Design:设计时,它允许 Entity Framework Core 功能(EF Core Migration)与 Microsoft SQL Server 一起使用。要访问命令行工具,我们需要在 project.json 的 tools 部分添加EntityFrameworkCore.Tools。

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

core_crud_6

修改后保存更改。包管理器控制台中的命令:打开包管理器控制台。

core_crud_7

输入以下命令然后按 Enter 键:

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

 core_crud_8 core_crud_9

命令窗口中的命令:打开命令窗口,导航到项目目录,输入:

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

这里会在命令窗口显示一个选项列表,我们将在 Commands 中使用 dbcontext。

core_crud_10

然后输入以下命令并按 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

这是执行并生成模型的两个过程的屏幕截图。我们将保留 DbEntities 文件夹进行工作,并删除另一个文件夹。

core_crud_12

配置 EF 服务:在 PhoneBookContext 类中添加构造函数。

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

在 Startup 类中,我们需要启用 EF 服务,为以下内容提供连接字符串:

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

我们已经在应用程序中配置了 EF 服务,接下来我们将使用 ASP.NET Core 中包含的 MVC6。

MVC 6:我们在上一篇文章中已经讨论过 MVC6,让我们再次简要回顾一下 MVC6 的新功能。

  1. MVC + Web API + Web Pages = MVC6
  2. 无 System.Web
  3. 网页和 HTTP 服务已统一
  4. 内置依赖注入
  5. 动态代码编译(Roslyn 编译器)
  6. 开源 &
  7. 支持跨平台构建和运行。
  8. 可以在 IIS 中托管,也可以自托管(IIS 外部)。

好的,现在让我们添加一个 WebApi Controller 来对数据库表执行 CRUD 操作。在解决方案资源管理器中,添加一个新的 api 文件夹,右键单击它 > 添加新项 > Web API Controller Class > 添加。修改初始模板。core_crud_13

API 控制器

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

core_crud_14

您可能会注意到 MVC6 属性路由中有一个新模式 [ ],即 **[RouteToken]**。这意味着路由令牌会自动获取控制器名称。

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

另一件事是,我们知道 Web API 默认会生成 XML,现在在 MVC 6 中,我们可以通过在类标签或方法标签上放置属性来设置一个属性,以将默认生成器更改为 JSON 类型。在我们的例子中,我们将其设置在方法标签上。

[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 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;
}

所以我们的 Web API 已经准备好处理与数据库的数据了,是时候处理客户端脚本了。

Angular V2:我们的 WebAPI 已经准备好处理来自服务器的数据。现在我们将使用 TypeScript(.ts)文件处理客户端代码。首先,我们需要创建一个主页面来展示我们的视图。core_crud_15

然后我们需要在应用程序启动时指向此 html 文件,因此让我们转到 startup.cs 文件添加以下代码片段。这是默认文件中间件的配置。

Startup.cs

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

需要添加库

using Microsoft.AspNetCore.Builder;

现在向 html 页面添加脚本库引用,并定义视图点以加载我们的应用程序组件视图。

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

然后我们需要引用我们的引导文件在页面上,它导入并启用我们的 angular 脚本到页面。

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

让我们将所有这些放在 Index.html 文件中。

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>

  引导、模型、组件和路由 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

/*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

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

让我们仔细看看下面的代码片段,我们在这里调用了服务方法,但遇到了未知术语 Subscribe - 它是做什么用的?下面我们有一个简单的解释。

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

Subscribe:要传递给 Observable 构造函数的订阅者函数。 

服务 在我们的服务文件中,我们有 Http 服务 [Get, GetByID, Post, Put, Delete],它连接 WebAPI 来执行创建、读取、更新和删除操作。GET ALL:执行一个带有 `get` http 方法的请求。用于对象集合

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

GET By ID:执行一个带有 `get` http 方法的请求。用于单个对象

//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:执行一个带有 `post` http 方法的请求。

//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:执行一个带有 `put` http 方法的请求。

//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:执行一个带有 `delete` http 方法的请求。

//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>] 表示在任何时间段内的任何一组值。这是 RxJS 的最基本构建块。让我们将其放入 Contact.service 文件中。

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

让我们讨论一下 Angular2 中的表单,Angular2 表单有两种策略:

  1. 模板驱动
  2. 模型驱动

 模板驱动 在模板驱动表单中,指令是声明式地添加到模板中的。

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

注意到验证器是以声明式方式与输入元素“required”一起添加的。 

模型驱动 在我们的示例应用程序中,我们使用了模型驱动表单,其中包含 ngFormModel 和 ngFormControl。这里 ngFormControl 与输入元素绑定,通过控件获取输入值。

ngFormModel:将其绑定到控制器变量“contactForm”。

<form [ngFormModel]="contactForm">

ngFormControl

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

ControlGroup 包含多个 Controls。

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

注入的 FormBuilder 使用生成器创建控件组,控件组以键值对的形式传递。

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

验证也在我们的组件中进行了检查。下面是我们完整的模型驱动表单。表单

<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>

  这是我们在应用程序中使用的完整的联系人视图页面。

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>

  以上就是我们在示例应用程序中使用 Angular 部分的所有内容,用于执行客户端操作。现在是时候构建和运行应用程序了。接下来我们将概述服务器配置。 

配置服务器IIS 外部(Weblistener):我们可以在没有 IIS 环境的情况下托管和运行我们的应用程序,我们需要添加命令对象来告诉托管使用 HTTP 服务器 weblistener(仅限 Windows)。

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

确保依赖项存在。

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

现在转到解决方案资源管理器,右键单击项目 > 属性 > 调试,将配置文件更改为 OutsideIIS。core_crud_16 设置启动 URL,然后保存并运行应用程序。core_crud_17 服务器将启动并显示托管环境详细信息。

core_crud_18

应用程序在 URL https://:5000 上运行,并提供详细的请求信息。

core_crud_19

IIS 内部(Kestrel):Kestrel 是一个跨平台 Web 服务器,可以在 IIS 或 Nginx 后面运行。

core_crud_20

从导航栏下拉列表中更改为 IIS Express,以使用 IIS 运行应用程序。好的,让我们运行我们的应用程序,看看它是如何工作的。

输出:在这里,我们可以看到应用程序的输出,带有欢迎消息,并且数据是通过我们的 MVC6 – WebAPI 从服务器列出的。在这里,我们可以执行具有必要验证的 CRUD 操作。 

core_crud_21

希望这会有所帮助:)

CRUD USING .NET CORE 1.0, ANGULAR V2, WEBAPI - CodeProject - 代码之家
© . All rights reserved.