【发布时间】:2019-08-05 19:49:45
【问题描述】:
我为他准备了 Web API 和 Angular 应用程序。
我在 web api 端启用了 cors 策略:
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy", b =>
{
b.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
}
);
});
app.UseCors("CorsPolicy");
我像这样从 Angular 发送获取请求:
this._httpClient.get(`WebApi link`);
但捕获错误:
WebSocket 握手期间出错:意外响应代码 400
我做错了什么?
这个链接在 PostMan 中完美运行,我得到了结果。
Web API 使用 win auth。
UPD
Web API 端在 Startup.cs 中有这个设置:
public class Startup
{
private readonly ILoggerFactory _loggerFactory;
public Startup(IHostingEnvironment env, ILoggerFactory loggerFactory)
{
AutomapperConfig.Init();
_loggerFactory = loggerFactory;
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
/// <summary>
/// This method gets called by the runtime. Use this method to add services to the container.
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddResponseCompression();
services.AddMvc();
services.AddAuthentication(HttpSysDefaults.AuthenticationScheme);
services.AddAuthorization(options =>
{
foreach (var action in Action.All)
options.AddPolicy(action.Name, policy =>
policy.Requirements.Add(new AssemblyStorageRequirement(action)));
});
services.AddSingleton<IAuthorizationHandler, AssemblyStorageRequirementHandler>();
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy", b =>
{
b.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
}
);
});
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" });
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);
});
services.AddOptions();
services.AddSingleton(Configuration); // IConfigurationRoot
services.AddSingleton<IConfiguration>(Configuration); // IConfiguration explicitly
return services.AddDiConfig(Configuration);
}
/// <summary>
/// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
/// </summary>
/// <param name="app"></param>
/// <param name="env"></param>
/// <param name="loggerFactory"></param>
/// <param name="appLifetime"></param>
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IApplicationLifetime appLifetime)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
loggerFactory.AddLog4Net();
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});
app.UseAuthentication();
app.UseResponseCompression();
app.UseCors("CorsPolicy");
app.UseMvc();
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
appLifetime.ApplicationStopped.Register(DiConfig.DisposeContainer);
}
}
Angular 端在 Startup.cs 中有这个设置:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
// In production, the Angular files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy", b =>
{
b.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.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseCors("CorsPolicy");
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSpaStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
{
// To learn more about options for serving an Angular SPA from ASP.NET Core,
// see https://go.microsoft.com/fwlink/?linkid=864501
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
}
}
请求标头:GET wss://localhost:44391/sockjs-node/616/kjiu00aa/websocket HTTP/1.1 主机:本地主机:44391 连接:升级编译指示:无缓存 缓存控制:无缓存升级:websocket 来源: https://localhost:44391 Sec-WebSocket-Version: 13 用户代理: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, 像壁虎)Chrome/72.0.3626.121 Safari/537.36 Accept-Encoding: gzip, 放气,br 接受语言:ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7 Sec-WebSocket-Key:Ia0VO1G8+d52FJG74UvsQw== Sec-WebSocket-Extensions: permesage-deflate; client_max_window_bits
响应标头:
HTTP/1.1 400 Bad Request Transfer-Encoding: chunked Vary: Origin 服务器:Kestrel 访问控制允许凭据:true 访问控制允许来源:https://localhost:44391 X-SourceFiles: =?UTF-8 2 B 4 RTpcUHJvamVjdHNcVEZTXE9jdG9wdXNTZXJ2aWNlc1xBc3NlbWJseVN0b3JhZ2VcQXNzZW1ibHlTdG9yYWdlV2ViU2l0ZVxBc3NlbWJseVN0b3JhZ2VXZWJTaXRlXHNvY2tqcy1ub2RlXDYxNlxraml1MDBhYVx3ZWJzb2NrZXQ =?= X-Powered-By:ASP.NET 日期:2019 年 3 月 15 日星期五 08:03:32 GMT
一般:
请求网址:wss://localhost:44391/sockjs-node/616/kjiu00aa/websocket 请求方法:GET 状态码:400 Bad Request
UPD
如果我注释掉代码中唯一使用 HttpClient 的地方,那么错误仍然显示...
所以问题不在于 WebApi
【问题讨论】:
-
@KirkLarkin,稍后再谈。也许我应该通过一个请求来获得其他东西?
-
我尝试添加 {withCredentials:true} 但没有帮助
-
您能否提供有关该错误在您浏览器的开发人员工具中显示的更多信息?以 400 失败的请求应该可以在网络选项卡中看到,并且可以帮助诊断。
-
错误消息表明该问题与您在问题中提到的 API 端点无关。
wss://localhost:44391/sockjs-node/...是通过 Angular CLI 返回到托管的 SPA 服务器的 web-socket 连接,因此在这个阶段很难诊断。下一步是查看服务器日志,看看在处理该请求时到底发生了什么。 -
@KirkLarkin,这个项目是从默认的带有 Angular 的 Visual Studio 模板创建的,之后我的改动很小。也许我应该安装某人?
标签: c# angular web asp.net-core