У меня есть веб-API и приложение Angular для него.
Я включил политику Cors на стороне веб-API:
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy", b =>
{
b.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
}
);
});
app.UseCors("CorsPolicy");
Я отправляю запрос от Angular следующим образом:
this._httpClient.get(`WebApi link`);
но выловить ошибку:
Ошибка при рукопожатии WebSocket: непредвиденный код ответа 400
Что я делаю не так?
Эта ссылка отлично работает в PostMan, и я получаю результат.
Веб-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);
}
}
Угловая сторона имеет этот параметр в 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
Хост: localhost: 44391 Подключение: Обновление Pragma: no-cache
Cache-Control: no-cache Обновление: websocket Происхождение:
https://localhost:44391 Sec-WebSocket-Version: 13 User-Agent:
Mozilla / 5.0 (Windows NT 6.1; Win64; x64) AppleWebKit / 537.36 (KHTML,
как Gecko) Chrome / 72.0.3626.121 Safari / 537.36 Accept-Encoding: gzip,
deflate, br Accept-Language: ru-RU, ru; q = 0,9, en-US; q = 0,8, en; q = 0,7
Sec-WebSocket-Key: Ia0VO1G8 + d52FJG74UvsQw == Sec-WebSocket-Extensions:
permessage-Deflate; client_max_window_bits
Заголовки ответа:
HTTP / 1.1 400 Bad-Transfer-Encoding: chunked Vary: Origin
Сервер: Kestrel Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://localhost:44391 X-SourceFiles:
=? UTF-8? B? RTpcUHJvamVjdHNcVEZTXE9jdG9wdXNTZXJ2aWNlc1xBc3NlbWJseVN0b3JhZ2VcQXNzZW1ibHlTdG9yYWdlV2ViU2l0ZVxBc3NlbWJseVN0b3JhZ2VXZWJTaXRlXHNvY2tqcy1ub2RlXDYxNlxraml1MDBhYVx3ZWJzb2NrZXQ =? =
X-Powered-By: ASP.NET Дата: Пт, 15 марта 2019 08:03:32 GMT
Общие сведения:
URL запроса: wss: // localhost: 44391 / sockjs-node / 616 / kjiu00aa / websocket
Метод запроса: ПОЛУЧИТЕ код состояния: 400 неправильный запрос
UPD
Если я закомментирую единственное место в коде, где используется HttpClient, то ошибка все равно покажет ...
Так что проблема не в WebApi