typescript Angular 4 - 如何从 ASP.Net web api 获取数据
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/46756083/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Angular 4 - How to get data from ASP.Net web api
提问by Sami-L
Using the famous Visual Studio 2017 Angular 4 template, I tested the side navbar buttons and could fetch the in-memory data.
使用著名的 Visual Studio 2017 Angular 4 模板,我测试了侧边导航栏按钮并可以获取内存数据。
Then I added to the project, a new ASP.Net Core 2.0 API controller connected to a database using Entity Framework, and got it to run with the 200 HTTP GET
result.
然后我将一个新的 ASP.Net Core 2.0 API 控制器添加到项目中,该控制器使用实体框架连接到数据库,并使其运行并得到200 HTTP GET
结果。
The controller code:
控制器代码:
#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<Todo> 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
Now, I wanted to display the resulting ASP.Net Core controller data using Angular, so I created a TypeScript component named “todo
” as below:
现在,我想使用 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;
}
And created its HTML component as below:
并创建其 HTML 组件如下:
<h1>Todo tasks</h1>
<p>This component demonstrates fetching Todo tasks from the server.</p>
<p *ngIf="!todo"><em>Loading...</em></p>
<table class='table' *ngIf="Todo">
<thead>
<tr>
<th>Id</th>
<th>Task Name</th>
<th>Is complete</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let Task of todo">
<td>{{ Task.Id }}</td>
<td>{{ Task.TaskName }}</td>
<td>{{ Task.Iscomplete }}</td>
</tr>
</tbody>
</table>
Then went to add its routing in Nav side bar menu, here is TypeScript code:
然后去Nav侧边栏菜单中添加它的路由,这里是TypeScript代码:
import { Component } from '@angular/core';
@Component({
selector: 'nav-menu',
templateUrl: './navmenu.component.html',
styleUrls: ['./navmenu.component.css']
})
export class NavMenuComponent {
}
And here is Navbar HTML code:
这是导航栏 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>
<span class='icon-bar'></span>
</button>
<a class='navbar-brand' [routerLink]="['/home']">TodoAngularUI</a>
</div>
<div class='clearfix'></div>
<div class='navbar-collapse collapse'>
<ul class='nav navbar-nav'>
<li [routerLinkActive]="['link-active']">
<a [routerLink]="['/home']">
<span class='glyphicon glyphicon-home'></span> Home
</a>
</li>
<li [routerLinkActive]="['link-active']">
<a [routerLink]="['/counter']">
<span class='glyphicon glyphicon-education'></span> Counter
</a>
</li>
<li [routerLinkActive]="['link-active']">
<a [routerLink]="['/fetch-data']">
<span class='glyphicon glyphicon-th-list'></span> Fetch data
</a>
</li>
<li [routerLinkActive]="['link-active']">
<a [routerLink]="['/api/todo']">
<span class='glyphicon glyphicon-apple'></span> Todo api
</a>
</li>
</ul>
</div>
</div>
And my app.component.ts
:
而我的app.component.ts
:
import { Component } from '@angular/core';
@Component({
selector: 'app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
}
The issue here is that when I click the menu button to get data nothing happens, all other buttons are working but not this one, and 200 result is still showing when use directly the browser URL.
这里的问题是,当我单击菜单按钮获取数据时,没有任何反应,所有其他按钮都在工作,但不是这个,并且直接使用浏览器 URL 时仍然显示 200 结果。
No error message, and I failed to find solution searching on the net for issues related to Non clickable buttons in Angular, and related to passing data from ASP.Net to Angular.
没有错误消息,我未能在网上找到与 Angular 中不可点击按钮相关的问题的解决方案,以及与将数据从 ASP.Net 传递到 Angular 相关的问题。
What am I doing wrong?
我究竟做错了什么?
采纳答案by Ben Cottrell
(Answer derived from my comments above)
(答案来自我上面的评论)
I have had a similar problem to this before using Microsoft's Angular 4 template.
在使用 Microsoft 的 Angular 4 模板之前,我遇到过类似的问题。
The Problem
问题
Microsoft provides the BASE_URL
string as part of their template - it's obtained by extracting the href
attribute from the base
tag in index.cshtml
(the BASE_URL string isn't part of the Angular framework).
Microsoft 提供该BASE_URL
字符串作为其模板的一部分 - 它是通过href
从base
标签中提取属性获得的index.cshtml
(BASE_URL 字符串不是 Angular 框架的一部分)。
The base
tag in index.cshtml should look like <base href="~/" />
base
index.cshtml 中的标签应该看起来像<base href="~/" />
Which means that anywhere using BASE_URL
in your Angular 4 project already has the BASE_URL suffixed with a /
character.
这意味着BASE_URL
在您的 Angular 4 项目中使用的任何地方都已经具有带有/
字符后缀的 BASE_URL 。
So looking at this component calling http.get
using that URL:
所以看看这个http.get
使用那个 URL调用的组件:
@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));
}
}
Note that your call to http.get(baseUrl + '/api/todo')
has a /
in front of /api/todo
- so the parameter passed into http.get
will look like http://example.com//api/todo
due to the extra /
from BASE_URL.
请注意,您的调用在 - 前面http.get(baseUrl + '/api/todo')
有一个- 因此由于来自 BASE_URL的额外参数,传入的参数看起来像。/
/api/todo
http.get
http://example.com//api/todo
/
The Solution
解决方案
Try http.get(baseUrl + 'api/todo')
instead (note the absence of /
in front of api/todo
) - the BASE_URL
string should already include that, if nothing else in the template has been changed.
http.get(baseUrl + 'api/todo')
改为尝试(注意/
前面没有api/todo
) -BASE_URL
如果模板中没有其他任何内容已更改,则字符串应该已经包含该内容。
Update 22-03-2018: Using HTTP POST
2018 年 3 月 22 日更新:使用 HTTP POST
As per the comment below, here's a quick example function for POST, assuming that baseUrl
and http
have both been injected into the constructor:
根据下面的评论,这里是 POST 的一个快速示例函数,假设baseUrl
和http
都已注入构造函数:
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));
}
}
And on the ASP.NET WebAPI side (which implicitly knows how to handle Content-Type
of application/json
in an HTTP POST request):
而在ASP.NET的WebAPI侧(其中隐含知道如何处理Content-Type
的application/json
在HTTP POST请求):
public class TodoController : Controller
{
[HttpPost]
public IActionResult Post([FromBody] Todo todo)
{
return Ok();
}
}