Angular 4 – 如何从ASP.Net web api获取数据

使用着名的Visual Studio 2017 Angular 4模板,我测试了侧导航按钮,可以获取内存中的数据。

然后我在项目中添加了一个新的ASP.Net Core 2.0 API控制器,它使用Entity Framework连接到数据库,并使其运行200 HTTP GET结果。

控制器代码:

 #region TodoController namespace TodoAngularUI.Controllers { [Route("api/[controller]")] public class TodoController : Controller { private readonly SchoolContext _context; #endregion public TodoController(SchoolContext DbContext) { _context = DbContext; if (_context.Todo.Count() == 0) { _context.Todo.Add(new Todo { TaskName = "Item1" }); _context.SaveChanges(); } } #region snippet_GetAll [HttpGet] public IEnumerable GetAll() { return _context.Todo.ToList(); } [HttpGet("{id}", Name = "GetTodo")] public IActionResult GetById(long id) { var item = _context.Todo.FirstOrDefault(t => t.Id == id); if (item == null) { return NotFound(); } return new ObjectResult(item); } #endregion 

现在,我想使用Angular显示生成的ASP.Net Core控制器数据,因此我创建了一个名为“ todo ”的TypeScript组件,如下所示:

 import { Component, Inject } from '@angular/core'; import { Http } from '@angular/http'; @Component({ selector: 'todo', templateUrl: './todo.component.html' }) export class TodoComponent { public Todo: task[]; constructor(http: Http, @Inject('BASE_URL') baseUrl: string) { http.get(baseUrl + '/api/todo').subscribe(result => { this.Todo = result.json() as task[]; }, error => console.error(error)); } } interface task { Id: number; TaskName: string; IsComplete: boolean; } 

并创建了HTML组件,如下所示:

 

Todo tasks

This component demonstrates fetching Todo tasks from the server.

Loading...

Id Task Name Is complete
{{ Task.Id }} {{ Task.TaskName }} {{ Task.Iscomplete }}

然后去Nav侧栏菜单中添加其路由,这里是TypeScript代码:

 import { Component } from '@angular/core'; @Component({ selector: 'nav-menu', templateUrl: './navmenu.component.html', styleUrls: ['./navmenu.component.css'] }) export class NavMenuComponent { } 

这是Navbar HTML代码:

 

我的app.component.ts

 import { Component } from '@angular/core'; @Component({ selector: 'app', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { } 

这里的问题是,当我单击菜单按钮以获取数据时没有任何反应,所有其他按钮都正在工作但不是这个按钮,直接使用浏览器URL时仍然显示200结果。

没有错误消息,我在网上找不到与Angular中的不可点击按钮相关的问题的搜索解决方案,并且无法将数据从ASP.Net传递到Angular。

我究竟做错了什么?

(答案来自我上面的评论)

在使用Microsoft的Angular 4模板之前,我遇到过类似的问题。


问题

Microsoft提供BASE_URL字符串作为其模板的一部分 – 它是通过从index.cshtmlbase标记中提取href属性获得的(BASE_URL字符串不是Angular框架的一部分)。

index.cshtml中的base标记应该看起来像

这意味着在Angular 4项目中使用BASE_URL任何地方都已经将BASE_URL后缀为/字符。

所以看看使用该URL调用http.get这个组件:

 @Component({ selector: 'todo', templateUrl: './todo.component.html' }) export class TodoComponent { public Todo: task[]; constructor(http: Http, @Inject('BASE_URL') baseUrl: string) { http.get(baseUrl + '/api/todo').subscribe(result => { this.Todo = result.json() as task[]; }, error => console.error(error)); } } 

请注意,您对http.get(baseUrl + '/api/todo')的调用在http.get(baseUrl + '/api/todo')前面有一个/ ,所以传递给http.get的参数看起来像http://example.com//api/todo由于额外/来自BASE_URL。


解决方案

请尝试http.get(baseUrl + 'api/todo') (注意api/todo前面没有api/todo ) – 如果模板中没有其他内容被更改,则BASE_URL字符串应该已包含该字符串。


更新22-03-2018:使用HTTP POST

根据下面的评论,这里是一个POST的快速示例函数,假设baseUrlhttp都被注入到构造函数中:

 import { Observable } from 'rxjs/rx'; import { Http, Headers, RequestOptions } from '@angular/http'; @Component({ selector: 'todo', templateUrl: './todo.component.html' }) export class TodoComponent { constructor(private http: Http, @Inject('BASE_URL') private baseUrl: string) { } post(todo: Todo) { let fullUrl = this.baseUrl + 'api/todo'; let headers = new Headers({ 'Content-Type': 'application/json' }); let options = new RequestOptions({ headers: headers }); this.http.post(fullUrl, JSON.stringify(todo), options) .subscribe(result => { console.log(result); }, error => console.error(error)); } } 

在ASP.NET WebAPI端(隐式知道如何在HTTP POST请求中处理application/json Content-Type of application/json ):

 public class TodoController : Controller { [HttpPost] public IActionResult Post([FromBody] Todo todo) { return Ok(); } }