Ionic 4 - 如何通过 Web API 将应用程序连接到现有 SQL 服务器?
Ionic 4 - How to connect app to existing SQL Server via Web API?
已经问过很多类似的问题,但是 none 对于这个版本的 Ionic 框架和 none 已经收到了可以实际帮助我的答案。
背景:
我制作了一个应用程序,需要从现有的 SQL 服务器获取数据。从研究来看,唯一可以做到这一点的方法是使用 Web API 作为中间件,因为 Ionic 无法直接连接到 SQL 服务器。
请参考本教程,因为这是我一直在关注的内容:https://www.youtube.com/watch?v=Js_8ijftKC0&index=21&list=PLaU76WfrROI6LO_YqTDd8ADul3xQoao5L&t=0s
目前我所在的位置:
- 我已经完成了教程的 Ionic 方面,添加了服务和所有 CRUD 操作等。
- 我在 Visual Studio 的 ASP.NET Web MVC 中创建了一个 Web API。
- API 已连接到我的 SQL 数据库并启用 CRUD 操作。
问题:
按照本教程多次学习后,不遗漏一个提示。 None Ionic return 中的 CRUD 方法。没有根据请求从数据库中更新或检索任何内容。
- 教程缺少什么?它甚至准确吗?
感谢任何帮助,提前致谢。
sql.service.ts
import { Injectable } from '@angular/core';
import { Http, Headers, RequestMethod, RequestOptions } from '@angular/http';
import { map } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class SqlService {
url:string="http://localhost:50287/api/APIDemo/"
constructor(private http: Http) { }
getAll(){
return this.http.get(this.url).pipe(map(res=>res.json()));
}
Create(name) {
var body={"name":name};
var header=new Headers({'Content-Type':'application/json'})
var option=new RequestOptions({method:RequestMethod.Post,headers:header})
return this.http.post(this.url + "Posttest",body,option).pipe(map(res=>res.json()))
}
Update(id, name) {
var body={"id":id,"name":name};
var header=new Headers({'Content-Type':'application/json'})
var option=new RequestOptions({method:RequestMethod.Post,headers:header})
return this.http.post(this.url,body,option).pipe(map(res=>res.json()))
}
Read(id) {
return this.http.get(this.url+id).pipe(map(res=>res.json()))
}
Delete(id) {
return this.http.delete(this.url+id).pipe(map(res=>res.json()))
}
}
sql.page.ts
import { Component, OnInit } from '@angular/core';
import { SqlService } from '../../services/sql.service'
@Component({
selector: 'app-sql',
templateUrl: './sql.page.html',
styleUrls: ['./sql.page.scss'],
})
export class SqlPage implements OnInit {
items=[];
id: string;
name: string;
constructor(public sql: SqlService) {
this.getAll()
}
ngOnInit() {
}
getAll() {
this.items=[];
this.sql.getAll().subscribe(data=>{
for(var i=0;i<data.length;i++){
this.items.push(data[i]);
}
})
}
Add() {
if(this.id==null){
this.sql.Create(this.name).subscribe(data=>{
this.name="";
this.getAll();
})
}else {
this.sql.Update(this.id, this.name).subscribe(data=>{
this.id=null
this.name=""
this.getAll()
})
}
}
Edit(item) {
this.id = item.id
this.name = item.name
}
Delete(item) {
this.sql.Delete(item.id).subscribe(data=>{
this.getAll()
})
}
}
sql.page.html
<ion-header>
<ion-toolbar>
<ion-title>sql</ion-title>
</ion-toolbar>
</ion-header>
<ion-content padding>
<ion-item>
<ion-label>Name</ion-label>
<ion-input type="text" [(ngModel)]="id" hidden></ion-input>
<ion-input type="text" [(ngModel)]="name"></ion-input>
</ion-item>
<ion-button (click)="Add()">Add</ion-button>
<ion-list>
<ul>
<li *ngFor="let items of items">
{{ item.name }}
<ion-button (click)="Edit(item)">Edit</ion-button>
<ion-button (click)="Delete(item)">Delete</ion-button>
</li>
</ul>
</ion-list>
</ion-content>
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';
import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { HttpClientModule } from '@angular/common/http';
import { EmailComposer } from '@ionic-native/email-composer/ngx';
import { EmailPageModule } from './pages/email/email.module';
import { MapsPageModule } from './pages/maps/maps.module';
import { CallNumber } from '@ionic-native/call-number/ngx';
import { HttpModule } from '@angular/http'
import { SqlService } from './services/sql.service'
@NgModule({
declarations: [AppComponent],
entryComponents: [],
imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule, HttpClientModule, EmailPageModule, MapsPageModule, HttpModule],
providers: [
StatusBar,
SplashScreen,
EmailComposer,
CallNumber,
SqlService,
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
],
bootstrap: [AppComponent]
})
export class AppModule {}
演示API (C#)
WebApiConfig.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Web.Http.Cors;
namespace DemoAPI
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.EnableCors(new EnableCorsAttribute(origins: "http://localhost:8100", headers: "*", methods: "*"));
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}
APIDemoController.cs
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Description;
using DemoAPI.Models;
namespace DemoAPI.Controllers
{
public class APIDemoController : ApiController
{
private demoEntities db = new demoEntities();
// GET: api/APIDemo
public IQueryable<test> Gettests()
{
return db.tests;
}
// GET: api/APIDemo/5
[ResponseType(typeof(test))]
public IHttpActionResult Gettest(int id)
{
test test = db.tests.Find(id);
if (test == null)
{
return NotFound();
}
return Ok(test);
}
// PUT: api/APIDemo/5
[ResponseType(typeof(void))]
public IHttpActionResult Puttest(int id, test test)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != test.id)
{
return BadRequest();
}
db.Entry(test).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!testExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
// POST: api/APIDemo
[HttpPost]
[ResponseType(typeof(test))]
public HttpResponseMessage Posttest(test test)
{
if (test.id == 0)
{
if (!ModelState.IsValid)
{
db.tests.Add(test);
db.SaveChanges();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, test);
response.Headers.Location = new Uri(Url.Link("DefaultAPI", new { id = test.id }));
return response;
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
else
{
if (ModelState.IsValid)
{
db.Entry(test).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
return Request.CreateResponse(HttpStatusCode.NotFound);
}
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, test);
response.Headers.Location = new Uri(Url.Link("DefaultAPI", new { id = test.id }));
return response;
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
}
// DELETE: api/APIDemo/5
[ResponseType(typeof(test))]
public IHttpActionResult Deletetest(int id)
{
test test = db.tests.Find(id);
if (test == null)
{
return NotFound();
}
db.tests.Remove(test);
db.SaveChanges();
return Ok(test);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
private bool testExists(int id)
{
return db.tests.Count(e => e.id == id) > 0;
}
}
}
我会尽量简化原来的答案。让我们来一个 HTTP GET
请求。
在您的服务中:
getAll(){
return this.http.get(this.url).pipe(map(res=>res.json()));
}
在网络中 API 您有一个控制器,您可以在其中定义一些操作。您的 HTTP 请求会像这样映射到以下路由:
routeTemplate: "api/{controller}/{id}"
Routing is how Web API matches a URI to an action
所以在网络中API你会创建一个像这样的动作:
// GET: api/APIDemo/getall
[HttpGet]
[ResponseType(typeof(test))]
public IHttpActionResult GetAll(int id)
{
test test = db.tests.Find(id);
if (test == null)
{
return NotFound();
}
return Ok(test);
}
您的样品请求可以是这样的:
localhost:8080/api/apidemo/getall?id=1
您还需要发出正确的 HTTP 请求,这里我们正在检索所有测试,
[HttpGet] 属性定义了一个 GET。
您应该阅读 Controller and Routing。
编辑:
好的,所以您需要创建一个与 Web 中的方法签名相匹配的对象 API,所以对于您的 "Create" 示例。
Create(name) {
// use JSON.Stringigy to get an JSON string
var body=JSON.stringify({id: 1, name:name});
var header=new Headers({'Content-Type':'application/json'})
var option=new RequestOptions({method:RequestMethod.Post,headers:header})
return this.http.post(this.url + "Posttest",body,option).pipe(map(res=>res.json()))
}
已经问过很多类似的问题,但是 none 对于这个版本的 Ionic 框架和 none 已经收到了可以实际帮助我的答案。
背景:
我制作了一个应用程序,需要从现有的 SQL 服务器获取数据。从研究来看,唯一可以做到这一点的方法是使用 Web API 作为中间件,因为 Ionic 无法直接连接到 SQL 服务器。
请参考本教程,因为这是我一直在关注的内容:https://www.youtube.com/watch?v=Js_8ijftKC0&index=21&list=PLaU76WfrROI6LO_YqTDd8ADul3xQoao5L&t=0s
目前我所在的位置:
- 我已经完成了教程的 Ionic 方面,添加了服务和所有 CRUD 操作等。
- 我在 Visual Studio 的 ASP.NET Web MVC 中创建了一个 Web API。
- API 已连接到我的 SQL 数据库并启用 CRUD 操作。
问题:
按照本教程多次学习后,不遗漏一个提示。 None Ionic return 中的 CRUD 方法。没有根据请求从数据库中更新或检索任何内容。
- 教程缺少什么?它甚至准确吗?
感谢任何帮助,提前致谢。
sql.service.ts
import { Injectable } from '@angular/core';
import { Http, Headers, RequestMethod, RequestOptions } from '@angular/http';
import { map } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class SqlService {
url:string="http://localhost:50287/api/APIDemo/"
constructor(private http: Http) { }
getAll(){
return this.http.get(this.url).pipe(map(res=>res.json()));
}
Create(name) {
var body={"name":name};
var header=new Headers({'Content-Type':'application/json'})
var option=new RequestOptions({method:RequestMethod.Post,headers:header})
return this.http.post(this.url + "Posttest",body,option).pipe(map(res=>res.json()))
}
Update(id, name) {
var body={"id":id,"name":name};
var header=new Headers({'Content-Type':'application/json'})
var option=new RequestOptions({method:RequestMethod.Post,headers:header})
return this.http.post(this.url,body,option).pipe(map(res=>res.json()))
}
Read(id) {
return this.http.get(this.url+id).pipe(map(res=>res.json()))
}
Delete(id) {
return this.http.delete(this.url+id).pipe(map(res=>res.json()))
}
}
sql.page.ts
import { Component, OnInit } from '@angular/core';
import { SqlService } from '../../services/sql.service'
@Component({
selector: 'app-sql',
templateUrl: './sql.page.html',
styleUrls: ['./sql.page.scss'],
})
export class SqlPage implements OnInit {
items=[];
id: string;
name: string;
constructor(public sql: SqlService) {
this.getAll()
}
ngOnInit() {
}
getAll() {
this.items=[];
this.sql.getAll().subscribe(data=>{
for(var i=0;i<data.length;i++){
this.items.push(data[i]);
}
})
}
Add() {
if(this.id==null){
this.sql.Create(this.name).subscribe(data=>{
this.name="";
this.getAll();
})
}else {
this.sql.Update(this.id, this.name).subscribe(data=>{
this.id=null
this.name=""
this.getAll()
})
}
}
Edit(item) {
this.id = item.id
this.name = item.name
}
Delete(item) {
this.sql.Delete(item.id).subscribe(data=>{
this.getAll()
})
}
}
sql.page.html
<ion-header>
<ion-toolbar>
<ion-title>sql</ion-title>
</ion-toolbar>
</ion-header>
<ion-content padding>
<ion-item>
<ion-label>Name</ion-label>
<ion-input type="text" [(ngModel)]="id" hidden></ion-input>
<ion-input type="text" [(ngModel)]="name"></ion-input>
</ion-item>
<ion-button (click)="Add()">Add</ion-button>
<ion-list>
<ul>
<li *ngFor="let items of items">
{{ item.name }}
<ion-button (click)="Edit(item)">Edit</ion-button>
<ion-button (click)="Delete(item)">Delete</ion-button>
</li>
</ul>
</ion-list>
</ion-content>
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';
import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { HttpClientModule } from '@angular/common/http';
import { EmailComposer } from '@ionic-native/email-composer/ngx';
import { EmailPageModule } from './pages/email/email.module';
import { MapsPageModule } from './pages/maps/maps.module';
import { CallNumber } from '@ionic-native/call-number/ngx';
import { HttpModule } from '@angular/http'
import { SqlService } from './services/sql.service'
@NgModule({
declarations: [AppComponent],
entryComponents: [],
imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule, HttpClientModule, EmailPageModule, MapsPageModule, HttpModule],
providers: [
StatusBar,
SplashScreen,
EmailComposer,
CallNumber,
SqlService,
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
],
bootstrap: [AppComponent]
})
export class AppModule {}
演示API (C#)
WebApiConfig.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Web.Http.Cors;
namespace DemoAPI
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.EnableCors(new EnableCorsAttribute(origins: "http://localhost:8100", headers: "*", methods: "*"));
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}
APIDemoController.cs
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Description;
using DemoAPI.Models;
namespace DemoAPI.Controllers
{
public class APIDemoController : ApiController
{
private demoEntities db = new demoEntities();
// GET: api/APIDemo
public IQueryable<test> Gettests()
{
return db.tests;
}
// GET: api/APIDemo/5
[ResponseType(typeof(test))]
public IHttpActionResult Gettest(int id)
{
test test = db.tests.Find(id);
if (test == null)
{
return NotFound();
}
return Ok(test);
}
// PUT: api/APIDemo/5
[ResponseType(typeof(void))]
public IHttpActionResult Puttest(int id, test test)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != test.id)
{
return BadRequest();
}
db.Entry(test).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!testExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
// POST: api/APIDemo
[HttpPost]
[ResponseType(typeof(test))]
public HttpResponseMessage Posttest(test test)
{
if (test.id == 0)
{
if (!ModelState.IsValid)
{
db.tests.Add(test);
db.SaveChanges();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, test);
response.Headers.Location = new Uri(Url.Link("DefaultAPI", new { id = test.id }));
return response;
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
else
{
if (ModelState.IsValid)
{
db.Entry(test).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
return Request.CreateResponse(HttpStatusCode.NotFound);
}
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, test);
response.Headers.Location = new Uri(Url.Link("DefaultAPI", new { id = test.id }));
return response;
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
}
// DELETE: api/APIDemo/5
[ResponseType(typeof(test))]
public IHttpActionResult Deletetest(int id)
{
test test = db.tests.Find(id);
if (test == null)
{
return NotFound();
}
db.tests.Remove(test);
db.SaveChanges();
return Ok(test);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
private bool testExists(int id)
{
return db.tests.Count(e => e.id == id) > 0;
}
}
}
我会尽量简化原来的答案。让我们来一个 HTTP GET
请求。
在您的服务中:
getAll(){
return this.http.get(this.url).pipe(map(res=>res.json()));
}
在网络中 API 您有一个控制器,您可以在其中定义一些操作。您的 HTTP 请求会像这样映射到以下路由:
routeTemplate: "api/{controller}/{id}"
Routing is how Web API matches a URI to an action
所以在网络中API你会创建一个像这样的动作:
// GET: api/APIDemo/getall
[HttpGet]
[ResponseType(typeof(test))]
public IHttpActionResult GetAll(int id)
{
test test = db.tests.Find(id);
if (test == null)
{
return NotFound();
}
return Ok(test);
}
您的样品请求可以是这样的:
localhost:8080/api/apidemo/getall?id=1
您还需要发出正确的 HTTP 请求,这里我们正在检索所有测试, [HttpGet] 属性定义了一个 GET。
您应该阅读 Controller and Routing。
编辑:
好的,所以您需要创建一个与 Web 中的方法签名相匹配的对象 API,所以对于您的 "Create" 示例。
Create(name) {
// use JSON.Stringigy to get an JSON string
var body=JSON.stringify({id: 1, name:name});
var header=new Headers({'Content-Type':'application/json'})
var option=new RequestOptions({method:RequestMethod.Post,headers:header})
return this.http.post(this.url + "Posttest",body,option).pipe(map(res=>res.json()))
}