来自 Microsoft SQL 服务器的数据已正确发送到 .NET Web API,但未显示在 Angular 中
Data from Microsoft SQL Server sent to .NET Web API correctly, but not showing up in Angular
我的数据库 table 看起来像这样 - 示例数据:
Table结构:
我现在正在尝试让所有行显示在 chrome devtools 的控制台上。
.NET Web API 如下所示;我在邮递员中检查过它工作正常。这是 Entity Framework API 控制器:
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.Cors;
using System.Web.Http.Description;
using template;
namespace template.Controllers
{
[EnableCors(origins: "*", headers: "*", methods: "*")]
public class templatesController : ApiController
{
private editorEntities db = new editorEntities();
// GET: api/templates
public IQueryable<template> Gettemplates()
{
return db.templates;
}
// GET: api/templates/5
[ResponseType(typeof(template))]
public IHttpActionResult Gettemplate(int id)
{
template template = db.templates.Find(id);
if (template == null)
{
return NotFound();
}
return Ok(template);
}
// PUT: api/templates/5
[ResponseType(typeof(void))]
public IHttpActionResult Puttemplate(int id, template template)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != template.tempID)
{
return BadRequest();
}
db.Entry(template).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!templateExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
// POST: api/templates
[ResponseType(typeof(template))]
public IHttpActionResult Posttemplate(template template)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.templates.Add(template);
try
{
db.SaveChanges();
}
catch (DbUpdateException)
{
if (templateExists(template.tempID))
{
return Conflict();
}
else
{
throw;
}
}
return CreatedAtRoute("DefaultApi", new { id = template.tempID }, template);
}
// DELETE: api/templates/5
[ResponseType(typeof(template))]
public IHttpActionResult Deletetemplate(int id)
{
template template = db.templates.Find(id);
if (template == null)
{
return NotFound();
}
db.templates.Remove(template);
db.SaveChanges();
return Ok(template);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
private bool templateExists(int id)
{
return db.templates.Count(e => e.tempID == id) > 0;
}
}
}
这是有效的 Web API 调用:
这是 .html 按下按钮时调用 getthem()
函数的地方。
<button (click)="getThem()"></button>
<!-- <mat-form-field appearance="fill">
<mat-label>Chose Template</mat-label>
<mat-select>
<mat-option *ngFor="let temp of Templates" [value]="temp.value">
{{temp.viewValue}}
</mat-option>
</mat-select>
</mat-form-field> -->
<div class="example-button-row">
<div class="example-flex-container">
<button>
<mat-icon>add</mat-icon>
</button>
<button class="save">Save Current Template</button>
</div>
</div>
这是 Angular 中的 .ts 文件,用于包含这 4 个属性的 class 模板
export interface template {
templateID: number,
templateName: string,
content: string,
version: number,
}
这是保持 api 调用的服务:
export class TemplatesService {
constructor(
private http:HttpClient,
) { }
getTemplates(): Observable<template[]>{
return this.http.get<template[]>('https://localhost:44334/api/templates');
}
}
这是要呈现数据的 Angular 组件的 .ts 文件。现在我只想看到它们正在到达,所以它们只是显示在控制台上。
@Component({
selector: 'app-template',
templateUrl: './template.component.html',
styleUrls: ['./template.component.css']
})
export class TemplateComponent implements OnInit {
templates: template[]=[];
constructor(
private templateService: TemplatesService
){}
ngOnInit(): void {
}
getThem(): void {
this.templateService.getTemplates()
.subscribe(templates=>this.templates=templates);
console.log(this.templates);
}
}
这是数据未显示在 devtools 源选项卡和控制台中的屏幕截图
网络选项卡
好吧,可能还有其他问题,但我马上发现您的异步代码有问题。这是您当前的代码,并附有注释,说明为什么它的行为不如您预期的那样:
// TODO: rename getThem. This is the most generic name to the
// point that it might as well be called x(). What about something
// like refreshTemplates()? Or getTemplates()?
getThem(): void {
// getTemplates() is asynchronous, which means it doesn't block
// further execution in this function...
this.templateService.getTemplates()
.subscribe(templates=>this.templates=templates);
// ... which means this will always be its' initial value because
// getTemplates hasn't completed yet. We need to wait for subscribe
// to emit a value.
console.log(this.templates);
}
因此,第一个建议是重构您的代码以等待您的 observable 在您 console.log 您的 属性 之前发出一个函数。您只需将 console.log 放入回调函数
即可完成此操作
getThem(): void {
// Retrieve templates and do stuff with emitted value
this.templateService.getTemplates().subscribe(templates=> {
this.templates = templates;
// Since we are calling this from inside our callback function,
// this.templates will be whatever our getTemplates() function
// emitted after we subscribed to it.
console.log(this.templates)'
});
}
下一个问题是您的网络选项卡显示待处理。那些曾经完成过吗?那里可能发生了其他事情。
我的数据库 table 看起来像这样 - 示例数据:
Table结构:
我现在正在尝试让所有行显示在 chrome devtools 的控制台上。
.NET Web API 如下所示;我在邮递员中检查过它工作正常。这是 Entity Framework API 控制器:
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.Cors;
using System.Web.Http.Description;
using template;
namespace template.Controllers
{
[EnableCors(origins: "*", headers: "*", methods: "*")]
public class templatesController : ApiController
{
private editorEntities db = new editorEntities();
// GET: api/templates
public IQueryable<template> Gettemplates()
{
return db.templates;
}
// GET: api/templates/5
[ResponseType(typeof(template))]
public IHttpActionResult Gettemplate(int id)
{
template template = db.templates.Find(id);
if (template == null)
{
return NotFound();
}
return Ok(template);
}
// PUT: api/templates/5
[ResponseType(typeof(void))]
public IHttpActionResult Puttemplate(int id, template template)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != template.tempID)
{
return BadRequest();
}
db.Entry(template).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!templateExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
// POST: api/templates
[ResponseType(typeof(template))]
public IHttpActionResult Posttemplate(template template)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.templates.Add(template);
try
{
db.SaveChanges();
}
catch (DbUpdateException)
{
if (templateExists(template.tempID))
{
return Conflict();
}
else
{
throw;
}
}
return CreatedAtRoute("DefaultApi", new { id = template.tempID }, template);
}
// DELETE: api/templates/5
[ResponseType(typeof(template))]
public IHttpActionResult Deletetemplate(int id)
{
template template = db.templates.Find(id);
if (template == null)
{
return NotFound();
}
db.templates.Remove(template);
db.SaveChanges();
return Ok(template);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
private bool templateExists(int id)
{
return db.templates.Count(e => e.tempID == id) > 0;
}
}
}
这是有效的 Web API 调用:
这是 .html 按下按钮时调用 getthem()
函数的地方。
<button (click)="getThem()"></button>
<!-- <mat-form-field appearance="fill">
<mat-label>Chose Template</mat-label>
<mat-select>
<mat-option *ngFor="let temp of Templates" [value]="temp.value">
{{temp.viewValue}}
</mat-option>
</mat-select>
</mat-form-field> -->
<div class="example-button-row">
<div class="example-flex-container">
<button>
<mat-icon>add</mat-icon>
</button>
<button class="save">Save Current Template</button>
</div>
</div>
这是 Angular 中的 .ts 文件,用于包含这 4 个属性的 class 模板
export interface template {
templateID: number,
templateName: string,
content: string,
version: number,
}
这是保持 api 调用的服务:
export class TemplatesService {
constructor(
private http:HttpClient,
) { }
getTemplates(): Observable<template[]>{
return this.http.get<template[]>('https://localhost:44334/api/templates');
}
}
这是要呈现数据的 Angular 组件的 .ts 文件。现在我只想看到它们正在到达,所以它们只是显示在控制台上。
@Component({
selector: 'app-template',
templateUrl: './template.component.html',
styleUrls: ['./template.component.css']
})
export class TemplateComponent implements OnInit {
templates: template[]=[];
constructor(
private templateService: TemplatesService
){}
ngOnInit(): void {
}
getThem(): void {
this.templateService.getTemplates()
.subscribe(templates=>this.templates=templates);
console.log(this.templates);
}
}
这是数据未显示在 devtools 源选项卡和控制台中的屏幕截图
网络选项卡
好吧,可能还有其他问题,但我马上发现您的异步代码有问题。这是您当前的代码,并附有注释,说明为什么它的行为不如您预期的那样:
// TODO: rename getThem. This is the most generic name to the
// point that it might as well be called x(). What about something
// like refreshTemplates()? Or getTemplates()?
getThem(): void {
// getTemplates() is asynchronous, which means it doesn't block
// further execution in this function...
this.templateService.getTemplates()
.subscribe(templates=>this.templates=templates);
// ... which means this will always be its' initial value because
// getTemplates hasn't completed yet. We need to wait for subscribe
// to emit a value.
console.log(this.templates);
}
因此,第一个建议是重构您的代码以等待您的 observable 在您 console.log 您的 属性 之前发出一个函数。您只需将 console.log 放入回调函数
即可完成此操作getThem(): void {
// Retrieve templates and do stuff with emitted value
this.templateService.getTemplates().subscribe(templates=> {
this.templates = templates;
// Since we are calling this from inside our callback function,
// this.templates will be whatever our getTemplates() function
// emitted after we subscribed to it.
console.log(this.templates)'
});
}
下一个问题是您的网络选项卡显示待处理。那些曾经完成过吗?那里可能发生了其他事情。