Angular 7 到 dotnetcore 2.1 web api 调用没有响应
Angular 7 to dotnetcore 2.1 web api call gives no response
下面是来自login.component.ts,
的代码
login() {
const val = this.form.value;
if (val.email && val.password) {
this.authService.login(val.email, val.password)
.subscribe(
data => {
if (data && data.Token) {
// store user details and jwt token in local storage to keep user logged in
//between page refreshes
localStorage.setItem('currentUser', JSON.stringify(data));
console.log("user logged in");
this.router.navigate([this.returnUrl]);
} else {
console.log("user not logged in");
}
},
error => {
this.error = error;
});
}
}
下面是来自 angular 服务的代码,
login(email: string, password: string) {
return this.http.post<User>(this.baseUrl + "Authenticate", { email,
password }, httpOptions);
}
下面是 dotnetcore 2.1 web api 操作的代码,
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using API.Utilities;
using Business.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
namespace API.Controllers
{
[Authorize]
[Produces("application/json")]
[Route("api/[controller]")]
public class UsersController : BaseController
{
private readonly AppSettings _appSettings;
public UsersController(IOptions<AppSettings> appSettings)
{
_appSettings = appSettings.Value;
}
[AllowAnonymous]
[HttpPost]
[Route("Authenticate")]
public IActionResult Authenticate([FromBody]User userParam)
{
var user = Authenticate(userParam.Email, userParam.Password);
if (user == null)
return BadRequest(new { message = "Username or password is incorrect" });
return Ok(user);
}
public User Authenticate(string username, string password)
{
//////code goes
return user;
}
}
}
}
在 fiddler 中,我总是可以看到长度为 -1 的 post 请求。不知道有什么问题有帮助吗?
以下来自startup.cs。我的 dotnetcore2.1 WEB 的 CORS 设置有什么缺陷 API 解决方案
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1).
AddJsonOptions(options => {
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
});
services.AddDistributedMemoryCache();
services.AddSession(options => {
// Set a short timeout for easy testing.
options.IdleTimeout = TimeSpan.FromSeconds(36000);
options.Cookie.HttpOnly = true;
});
services.AddCors(options => {
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseStaticFiles();
app.UseCors(x => x
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
app.UseSession();
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseMvc();
}
我曾经遇到过一个问题,我的控制器与我的虚拟 api 路由位于同一目录中。看起来这个可能对你来说是同样的问题。你有:
namespace API.Controllers
{
[Authorize]
[Produces("application/json")]
[Route("api/[controller]")]
public class UsersController : BaseController
{
现在,我的假设是(根据您的命名空间)您的控制器所在的目录是:api/{controllerName}
.
那么你的 api 路线是:api/[controller]
。这意味着您现在可以在同一路径上拥有一个实际目录和一个虚拟目录。当您尝试访问 api 时,dotnet 会混淆您是尝试访问目录文件还是 api 路由。在某些情况下,这 return 是一个 401
错误,其他人(取决于浏览器)将 return 你什么都没有。
您可以很容易地测试这个理论,方法是暂时将您的 api 路线更改为 test/[controller]
之类的路线,然后尝试击中它。
如果这解决了问题,那么您有 2 个选择:
- 更改您的 api 路线。
- 更改您的控制器目录。
您应该考虑到您的 WEB API 服务是从与您的 Angular UI 不同的端口访问的。在开发模式下托管您的 UI 的是 Angular Cli。这意味着为您的 WEB API 启用 CORS 并不一定为 Angular 的 UI 启用它们。
根据您发布的图像的外观,您的 Web API 的 URL 是 http://localhost:44389
,但 referer 是 http://localhost:4200
。
在开发阶段解决这个问题的一种方法是在您的 ClientApp 根文件夹中添加一个 proxyconfig.json
文件,其配置类似于:
{
"/api/*": {
"target": "https://localhost:44389",
"secure": true,
"changeOrigin": true
}
}
这样浏览器会解释从您的 Angular UI 到您的 WEB API 的请求来自同一来源。
如果您的 WEB API 和 Angular UI 将在生产模式下托管在同一台服务器上,我建议避免使用 CORS。这是一篇关于该主题的好文章:https://medium.freecodecamp.org/the-best-ways-to-connect-to-the-server-using-angular-cli-b0c6b699716c
注意:您可能需要提供 proxyconfig.json
文件,方法如下:https://www.codeproject.com/Tips/1259121/%2FTips%2F1259121%2FAngular-Proxy-Configuration-for-API-Calls
原因是基础 URL 中的 HTTP。当我将基础 URL 更新为 HTTPS 时,它开始工作了。
下面是来自login.component.ts,
的代码login() {
const val = this.form.value;
if (val.email && val.password) {
this.authService.login(val.email, val.password)
.subscribe(
data => {
if (data && data.Token) {
// store user details and jwt token in local storage to keep user logged in
//between page refreshes
localStorage.setItem('currentUser', JSON.stringify(data));
console.log("user logged in");
this.router.navigate([this.returnUrl]);
} else {
console.log("user not logged in");
}
},
error => {
this.error = error;
});
}
}
下面是来自 angular 服务的代码,
login(email: string, password: string) {
return this.http.post<User>(this.baseUrl + "Authenticate", { email,
password }, httpOptions);
}
下面是 dotnetcore 2.1 web api 操作的代码,
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using API.Utilities;
using Business.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
namespace API.Controllers
{
[Authorize]
[Produces("application/json")]
[Route("api/[controller]")]
public class UsersController : BaseController
{
private readonly AppSettings _appSettings;
public UsersController(IOptions<AppSettings> appSettings)
{
_appSettings = appSettings.Value;
}
[AllowAnonymous]
[HttpPost]
[Route("Authenticate")]
public IActionResult Authenticate([FromBody]User userParam)
{
var user = Authenticate(userParam.Email, userParam.Password);
if (user == null)
return BadRequest(new { message = "Username or password is incorrect" });
return Ok(user);
}
public User Authenticate(string username, string password)
{
//////code goes
return user;
}
}
}
}
在 fiddler 中,我总是可以看到长度为 -1 的 post 请求。不知道有什么问题有帮助吗?
以下来自startup.cs。我的 dotnetcore2.1 WEB 的 CORS 设置有什么缺陷 API 解决方案
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1).
AddJsonOptions(options => {
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
});
services.AddDistributedMemoryCache();
services.AddSession(options => {
// Set a short timeout for easy testing.
options.IdleTimeout = TimeSpan.FromSeconds(36000);
options.Cookie.HttpOnly = true;
});
services.AddCors(options => {
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseStaticFiles();
app.UseCors(x => x
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
app.UseSession();
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseMvc();
}
我曾经遇到过一个问题,我的控制器与我的虚拟 api 路由位于同一目录中。看起来这个可能对你来说是同样的问题。你有:
namespace API.Controllers
{
[Authorize]
[Produces("application/json")]
[Route("api/[controller]")]
public class UsersController : BaseController
{
现在,我的假设是(根据您的命名空间)您的控制器所在的目录是:api/{controllerName}
.
那么你的 api 路线是:api/[controller]
。这意味着您现在可以在同一路径上拥有一个实际目录和一个虚拟目录。当您尝试访问 api 时,dotnet 会混淆您是尝试访问目录文件还是 api 路由。在某些情况下,这 return 是一个 401
错误,其他人(取决于浏览器)将 return 你什么都没有。
您可以很容易地测试这个理论,方法是暂时将您的 api 路线更改为 test/[controller]
之类的路线,然后尝试击中它。
如果这解决了问题,那么您有 2 个选择:
- 更改您的 api 路线。
- 更改您的控制器目录。
您应该考虑到您的 WEB API 服务是从与您的 Angular UI 不同的端口访问的。在开发模式下托管您的 UI 的是 Angular Cli。这意味着为您的 WEB API 启用 CORS 并不一定为 Angular 的 UI 启用它们。
根据您发布的图像的外观,您的 Web API 的 URL 是 http://localhost:44389
,但 referer 是 http://localhost:4200
。
在开发阶段解决这个问题的一种方法是在您的 ClientApp 根文件夹中添加一个 proxyconfig.json
文件,其配置类似于:
{
"/api/*": {
"target": "https://localhost:44389",
"secure": true,
"changeOrigin": true
}
}
这样浏览器会解释从您的 Angular UI 到您的 WEB API 的请求来自同一来源。
如果您的 WEB API 和 Angular UI 将在生产模式下托管在同一台服务器上,我建议避免使用 CORS。这是一篇关于该主题的好文章:https://medium.freecodecamp.org/the-best-ways-to-connect-to-the-server-using-angular-cli-b0c6b699716c
注意:您可能需要提供 proxyconfig.json
文件,方法如下:https://www.codeproject.com/Tips/1259121/%2FTips%2F1259121%2FAngular-Proxy-Configuration-for-API-Calls
原因是基础 URL 中的 HTTP。当我将基础 URL 更新为 HTTPS 时,它开始工作了。