使用 HttpClient 和 RXJS 将数据发布到 Web API withCredentials: true
Posted
技术标签:
【中文标题】使用 HttpClient 和 RXJS 将数据发布到 Web API withCredentials: true【英文标题】:Using HttpClient and RXJS to POST data to Web API withCredentials: true 【发布时间】:2018-07-24 21:58:35 【问题描述】:我有一个Angular
服务已连接到我的.NET Web API
,我正在尝试将POST
一些数据发送到API。目前我使用的是HTTP
而不是HttpClient
,而且我没有发送任何数据。但服务已成功连接到 API。
在将实际数据从我的 Angular 控制器传递到服务(进而传递到 API)以及在服务中实现 HttpClient
方面需要帮助。到目前为止,我的控制器只是调用了我的服务的 myFunction()
函数,并且没有传递任何参数,因此没有数据。我不确定在服务的 RXJS
部分的哪个位置附加我的数据。
注意:但是我实现了这个,由于我的 API 的配置,我仍然需要它通过withCredentials: true
Web API 控制器:
namespace api.controllers
[Authorize]
public class ValuesController : ApiController
static List<string> strings = new List<string>()
"value0", "value1", "value2"
;
// GET api/values
public IEnumerable<string> Get()
return strings;
// GET api/values/5
public string Get(int id)
return "value";
// POST api/values
public void Post([FromBody]string value)
strings.Add(value);
// PUT api/values/5
public void Put(int id, [FromBody]string value)
// DELETE api/values/5
public void Delete(int id)
Web API web.config 文件(CORS 设置):
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="http://localhost:5200" />
<add name="Access-Control-Allow-Headers" value="*" />
<add name="Access-Control-Allow-Methods" value="GET,POST,PUT,DELETE,OPTIONS" />
<add name="Access-Control-Allow-Credentials" value="true" />
</customHeaders>
</httpProtocol>
myComponent.component.ts:
myService: MyService;
constructor(myService: MyService)
this.myService = myService;
this.myService.myFunction();
myService.service.ts:
import Injectable from '@angular/core';
import Http, Response, Request, Headers from '@angular/http';
// import HttpClient, HttpResponse, HttpRequest, HttpHeaders, HttpInterceptor, HttpHandler, HttpEvent from '@angular/common/http';
import Observable from 'rxjs';
import from from 'rxjs';
import map, filter, catchError, mergeMap from 'rxjs/operators';
@Injectable(
providedIn: 'root'
)
export class MyService
http: Http;
constructor(http: Http)
this.http = http;
;
public myFunction()
let request = new Request(
method: "POST",
url: "http://localhost:9090/api/values",
withCredentials: true
);
return this.http.request(request)
.pipe(map(res => res.json()))
.subscribe(
data => console.warn(data),
err => console.error(err),
() => console.log("empty")
);
如何从我的控制器将一些实际数据附加到此服务?我该如何调整服务以使用 HttpClient 呢?我尝试将所有http: Http
引用更改为HttpClient
,完成所有HttpClient
导入并注释掉.map/json portions
,但我仍然在return this.http.request(request)
行中的request
参数下看到一条红线我这样做时的服务。
【问题讨论】:
【参考方案1】:我使用这个概念,希望它也适用于你。
为您的数据创建属性类(将其与您的 .net API 上的类匹配),这也提供了简单的数据处理 型号
export class MyData
username:string;
password:string;
isAuthenticated:boolean;
服务
import Http, Response, Request, Headers from '@angular/http';
export class MyService
constructor(private http: Http)
public myFunction(body:MyData)
let url = 'http://localhost:9090/api/values'
return this.http.post(url,body)
.pipe(map(res => res.json()))
TS
returnValue:any;
myData:MyData;
constructor(private service:MyService)
this.myData = new MyData();
myFunction()
this.myData.username = 'anything';
this.myData.password = 'mypw';
this.myData.isAuthenticated = true;
this.returnValue = this.service.myFunction(this.myData)
.subscribe(res=>console.log(res))
.NET API
[HttpPost]
public void MYAPI([FromBody]MyData model)
string uname = model.username;
string pw = model.password;
【讨论】:
谢谢!您会注意到,在我的示例中,我将withCredentials: true
键/值对传递给了服务中的myFunction
。由于我的 API 配置,这是我必须具备的。如何在您的示例中包含 withCredentials: true
?
嗨,Kyle,您能否解决问题(发帖时传递凭据?)【参考方案2】:
为了使用 HttpClient,您必须在 app.module.ts
中导入 HttpClientModule
HttpModule
并开始注入 HttpClient
http
中的对象
@Injectable(
providedIn: 'root'
)
export class MyService
constructor(private http: HttpClient)
;
public myFunction(body)
let requestOptions = withCredentials : true ;
return this.http.post("http://localhost:9090/api/values",body,requestOptions);
当你使用 HttpClient 时你不需要做
.map(res => res.json())
组件
constructor(myService: MyService)
this.myService = myService;
this.myService.myFunction(username:'test',password:'123465')
.subscribe(data => console.warn(data), err => console.error(err),() => console.log("empty")
);
通常您不需要订阅您的服务,因此您可以获得 数据到组件
ngOnInit
作为一般的良好做法,您必须在 ngOninit 方法
complete guide about http , RequestOptions
最后这是打字稿提示
这是简写语法
constructor(private http: HttpClient)
;
到这里
private http: HttpClient;
constructor(http: HttpClient)
this.http = http
;
【讨论】:
如果你写constructor(private myService: MyService) ...
这个组件会比你可以在everythere使用this.myService
更干净。
我在最后写了一个提示,这样他就不会感到困惑@DanielHabenicht
非常感谢!在我让它工作之前还有一个问题。您会注意到,在我的示例中,我将withCredentials: true
键/值对传递给了服务中的myFunction
。由于我的 API 配置,这是我不能没有的。如何在您的示例中包含 withCredentials: true
?
@KyleVassella 我已经更新了我的答案,并告诉你如何设置请求选项
再次感谢。我是如此接近。但是使用你的例子,我现在得到一个401 (Unauthorized)
错误,和一个Response for preflight has invalid HTTP status code 401
,就像我在实现我原来的withCredentials: true
之前一样。我在示例中的操作方式有效,但您的示例无效。 :/ 我查看了其他答案,它们与您的示例类似:***.com/questions/50606752/… 有什么想法吗?【参考方案3】:
除了服务之外,您的代码看起来还不错。 我还看到你的 API 有 [Authorize]。你需要通过授权
例如:
const httpOptions =
headers: new HttpHeaders(
'Authorization': myToken
),
withCredentials: true
;
在您的 Http 请求上,这样您就不会收到需要授权的错误。
此参考可能有用:https://angular.io/guide/security
使用 HttpClient 的服务:
import Injectable from '@angular/core';
import HttpClient, HttpHeaders from '@angular/common/http';
import Observable from 'rxjs';
// api path
const API_URL = 'http://10.111.1.23:80/api/my_api/api/yourController';
// add http headers.
const httpOptions =
headers: new HttpHeaders(
'Content-Type': 'application/json'
)
;
@Injectable()
export class MyService
// inject the Http Client to the constructor
constructor(private _http: HttpClient) ;
myFunction(entity: any): Observable<yourModel>
// using http client the return value of you api is
// directly map to your model
return this._http.post<yourModel>(API_URL ,
entity, httpOptions);
);
【讨论】:
Authorization
部分是我卡住的地方。无论我尝试什么,当POST
ing 数据时,我仍然会收到OPTIONS 401 (unauthorized)
错误。我已启用 cors 等。**我的 Web API
目前正在使用 Windows Authentication
。我相信这可能是 [Authorize]
属性相关的内容。我什至可以将什么作为'Authorization': mytoken
的值传递?什么会代替mytoken
?谢谢你的回答。
myToken 是一个包含 jwt 令牌的变量(请参阅 jwt.io),在我的情况下,我将令牌存储在 localStorage 中,然后检索它并将其存储到 myToken 变量中,然后将其附加到我的授权标头。
以上是关于使用 HttpClient 和 RXJS 将数据发布到 Web API withCredentials: true的主要内容,如果未能解决你的问题,请参考以下文章