使用 Angular 2 调用 Web API 控制器

Posted

技术标签:

【中文标题】使用 Angular 2 调用 Web API 控制器【英文标题】:Call web API controller using Angular 2 【发布时间】:2016-08-09 12:19:10 【问题描述】:

我是 Angular2 的新手。我想在我的 MVC6 项目中使用 Angular2 调用 API。我尝试了很多事情(包括Angular2 calling ASP.NET Web API 的指南),但都没有成功。

我不知道我应该从哪里开始,或者需要哪些文件。

【问题讨论】:

见***.com/a/34758630/5043867 这里的没有成功是什么意思?出了什么问题? 【参考方案1】:

我会查看 Github 上的一些示例,看看其他人是如何做到的。有许多事情必须恰到好处才能使其正常工作,并且在您启动并运行之前,错误可能是模糊的。

为您的项目添加一个 Web API 控制器类。为了确保一开始一切正常,我建议将您的 HttpGet 属性硬编码为“api/values”。

ValuesController.cs.

    public class ValuesController : Controller
    
      [HttpGet("api/values")]
      public IActionResult Get()
      
          return new JsonResult(new string[]  "value1", "value2" );
      

Startup.Cs. 您需要 angular2 路由不干扰 ASP.NET 的路由。这意味着如果出现 404 错误,您需要将 index.html 提供给客户端。 app.Use lambda 实现了这一点。请注意,它在调用 app.UseDefaultFiles() 和 app.UseStaticFiles() 之前

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    
        ...
        var angularRoutes = new[] 
             "/home"
         ;

        app.Use(async (context, next) =>
        
            if (context.Request.Path.HasValue && null != angularRoutes.FirstOrDefault(
                (ar) => context.Request.Path.Value.StartsWith(ar, StringComparison.OrdinalIgnoreCase)))
            
                context.Request.Path = new PathString("/");
            
            await next();
        );

        app.UseDefaultFiles();
        app.UseStaticFiles();
        app.UseMvc(routes =>
        
            routes.MapRoute(
                name: "default",
                template: "controller=Home/action=Index/id?");
        );
    

完成此设置后,您应该使用 Postman 测试您的 API,以确保路由按您希望的方式工作。如果这不起作用,它将在 Angular 中不起作用。我在我的 Visual Studio 项目调试设置中将 http://localhost:5001/ 设置为我的 App URL

如果工作正常,继续使用 Angular 2 加载它。您需要在 html 文件中的 head 标记之后使用基本元素。这告诉 Angular 路由器 URL 的静态部分是什么:

Index.html

    <base href="/">

接下来,您需要在 Angular2 中创建一个服务以从您的 API 中获取值: dataService.ts

import  Http, Response, Headers  from '@angular/http';
import 'rxjs/add/operator/map'
import  Observable  from 'rxjs/Observable';
import  Configuration  from '../app.constants';

@Injectable()
export class DataService  
  private actionUrl: string;
  constructor(private _http: Http, private _configuration: Configuration) 
    this.actionUrl = 'http://localhost:5001/api/values/';


public GetAll = (): Observable<any> => 
    return this._http.get(this.actionUrl)
        .map((response: Response) => <any>response.json())
        .do(x => console.log(x));

RxJS 中的 .do 操作符非常方便。它将允许您调试您是否正确地从您的 API 获取值。见Andre Staltz's blog for more details。

最后,创建一个组件来使用该服务: app.component.ts

import  Observable  from 'rxjs/Observable';
import  Component, OnInit  from '@angular/core';
import  Http  from '@angular/http';
import  DataService  from '../services/DataService';

@Component(
    selector: 'app',
    template: `My Values: <ul><li *ngFor="let value of values">
        <span>value.id </span>
      </li></ul>`,
    providers: [DataService]
)

export class AppComponent implements OnInit 
  public values: any[];
  constructor(private _dataService: DataService) 
  ngOnInit() 
    this._dataService
        .GetAll()
        .subscribe(data => this.values = data,
        error => console.log(error),
        () => console.log('Get all complete'));
  

【讨论】:

绝妙的答案!但是,我在 app.constants 的数据服务中遇到错误。这个 app.constant 文件应该是什么样的? 谢谢!它只是一个包含常量的文件。我不应该包含在 sn-p 中。您应该可以毫无问题地删除该行。 太棒了。谢谢! 我需要添加 import 'rxjs/add/operator/do';让 .do 日志记录工作! 您好,感谢您的回复。问题:为什么响应作为数组传递?公共值:任何[];【参考方案2】:

这就是我的应用程序(angular2 作为前端,带有 Web API 核心)-

    使用实体框架创建一个控制器,该框架提供所有操作 - GET、POST、PUT 和 DELETE。如果您不熟悉 Web api 和实体框架,请参考此链接 - https://docs.efproject.net/en/latest/platforms/aspnetcore/existing-db.html

    在 Web API 中启用 CORS

[这样做是为了处理从 localhost:3000 (angular2) 到 localhost:59024 (webapi) 的交叉通信]

首先,在project.json中添加依赖-"Microsoft.AspNetCore.Cors": "1.0.0",

然后像这样在 startup.cs 中启用 CORS-

app.UseCors(builder => 
    builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();
);

您可以在此处找到有关 CORS 的更多信息 - https://docs.asp.net/en/latest/security/cors.html

3.在Angular2前端,你可以这样写你的服务组件-

@Injectable()
export class WebApiService 

    private _webApiUrl = 'http://localhost:59024/api/EmployeeMastersAPI'; 

        constructor(private _http: Http)  

        

    getEmployees(): Observable<> 
        return this._http.get(this._webApiUrl)
            .map((response: Response) => <any[]> response.json())
             .do(data => console.log('All: ' +  JSON.stringify(data)))
             .catch(this.handleError)
            ;
    

    getEmployee(id: number): Observable<IEmployee> 
        return this.getEmployees()
            .map((emp: IEmployee[]) => emp.find(p => p.EMPID === id));
    

    addEmployeesDetails(emp) 
        var headers = new Headers();
        headers.append('Content-Type', 'application/json; charset=utf-8');
        console.log('add emp : ' +  JSON.stringify(emp));
        this._http.post(this._webApiUrl, JSON.stringify(emp),  headers: headers ).subscribe();

    

    private handleError(error: Response) 
        console.error(error);
        return Observable.throw(error.json().error || 'Server error');
    


看看这是否有帮助。

【讨论】:

以上是关于使用 Angular 2 调用 Web API 控制器的主要内容,如果未能解决你的问题,请参考以下文章

使用 Active Directory 令牌从 Angular 到 Web API 应用程序进行安全 API 调用

Angular 2 Http 删除与 Web API REST 一起使用的标头

Web Api 2 和 Angular 之间的 CORS 错误

如何从 Angular 7 调用 Web API 返回布尔值?

如何在使用 AngularJS/Web API/Angular-ui-router 的指令中调用 $http.put 服务后更新页面

Angular 2/Web Api - json 解析错误语法错误意外结束输入