[我正在使用信号来获取我的角度应用程序中的实时数据,并使用.net core 2.2 API作为后端,但是当我运行项目时,在浏览器控制台中出现了CORS错误。
VehicleHub.cs
using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BusinessLayer.HubConfig
{
public class VehicleHub:Hub
{
public int id { get; set; }
public string name { get; set; }
public string vehicleType { get; set; }
public string modelNo { get; set; }
public string registrationNo { get; set; }
public int? lcsVehicleNo { get; set; }
public int relationShipOfficerId { get; set; }
public int driverId { get; set; }
public string driverName { get; set; }
public string relationShipOfficerName { get; set; }
public bool isActive { get; set; }
public DateTime createdOn { get; set; }
public string createdBy { get; set; }
public DateTime modifiedOn { get; set; }
public string modifyBy { get; set; }
public int locationId { get; set; }
public int createdById { get; set; }
public int? modifyById { get; set; }
}
}
这是我的starup.cs文件
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using BusinessLayer.Helpers;
using MatechEssential;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using WebAPICore.Helpers;
using WebAPICore.middleware;
using WebAPICore.Services;
using WebAPICore.Utility;
using BusinessLayer.HubConfig;
namespace WebAPICore
{
public class Startup
{
private readonly IHostingEnvironment _hostingEnvironment;
public Startup(IConfiguration configuration, IHostingEnvironment env)
{
Configuration = configuration;
_hostingEnvironment = env;
}
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.AddCors(o => o.AddPolicy("CorsPolicy", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.SetIsOriginAllowed((host) => true);
}));
services.AddSignalR();
services.AddMvc(options =>
{
options.Filters.Add(new ErrorHandlingFilter());
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
// configure strongly typed settings objects
var appSettingsSection = Configuration.GetSection("AppSettings");
services.Configure<AppSettings>(appSettingsSection);
// configure jwt authentication
var appSettings = appSettingsSection.Get<AppSettings>();
SQLHelper._ConStr = appSettings.ConnectionString != null? appSettings.ConnectionString:"" ;
var key = Encoding.ASCII.GetBytes(appSettings.Secret);
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = "bearer";
x.DefaultChallengeScheme = "bearer";
})
.AddJwtBearer("bearer", options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = false,
ValidateIssuer = false,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(appSettings.Secret)),
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
// TimeSpan.Zero //the default for this setting is 5 minutes
};
options.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
{
context.Response.Headers.Add("Token-Expired", "true");
}
return Task.CompletedTask;
}
};
options.SaveToken = true;
});
var physicalProvider = _hostingEnvironment.ContentRootFileProvider;
var embeddedProvider = new EmbeddedFileProvider(Assembly.GetEntryAssembly());
var compositeProvider = new CompositeFileProvider(physicalProvider, embeddedProvider);
string absolutePath = compositeProvider.GetFileInfo("/SetupFiles/MasterSetupData.xml").PhysicalPath;
XmlToList.xmlFileType = absolutePath;
services.AddTransient<IHttpContextAccessor, HttpContextAccessor>();
services.AddTransient<UserResolverService>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory logger)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseApiExceptionHandler(logger);
}
else
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
app.UseApiExceptionHandler(logger); //use global exception handlers
}
app.UseSignalR(routes =>
{
routes.MapHub<VehicleHub>("/Utility/GetAllVehicles");
});
// global cors policy
app.UseCors("CorsPolicy");
app.UseAuthentication();
app.UseHttpsRedirection();
app.UseResponseWrapper();
//app.UseAPIResponseWrapperMiddleware();
app.UseOptions();
app.UseMvc();
}
}
}
UtilityController.cs
[Route("api/[controller]")]
[ApiController]
[EnableCors("CorsPolicy")]
public class UtilityController : ControllerBase
{
private UserModel _currentUser;
private IHubContext<VehicleHub> _hub;
public UtilityController(UserResolverService userService, IHubContext<VehicleHub> hub)// , IUserService userService
{
_hub = hub;
_currentUser = userService.getUserInfo();
}
[HttpGet]
[Route("GetAllVehicles")]
public IActionResult GetAllVehicles()
{
try
{
_hub.Clients.All.SendAsync("transferchartdata", UtilityFuncation.GetVehicleAll());
return Ok(new { Message = "Request Completed" });
}
catch (Exception exp)
{
return NotFound(CommonApiResponse.Create(HttpStatusCode.InternalServerError, "Error Date Not Fetch", exp.Message));
}
}
}
我从Stackoverflow的控制器中删除了其他操作/方法
signal-r.service.ts
import { Injectable } from '@angular/core';
import * as signalR from "@aspnet/signalr";
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class SignalRService {
public data: VehicleModel[]
private hubConnection: signalR.HubConnection
options: signalR.IHttpConnectionOptions = {
accessTokenFactory: () => {
let token = localStorage.getItem("token")
return `Bearer ${token}`;
},
};
public startConnection = () => {
this.hubConnection = new signalR.HubConnectionBuilder()
.withUrl('http://localhost:50915/Utility/GetAllVehicles', this.options)
.build();
this.hubConnection
.start()
.then(() => console.log('Connection started'))
.catch(err => console.log('Error while starting connection: ' + err))
}
public addTransferChartDataListener = () => {
this.hubConnection.on('transferchartdata', (data) => {
this.data = data;
console.log(data);
});
}
constructor() { }
}
export interface VehicleModel {
id : any
name : any
vehicleType : any
modelNo : any
registrationNo : any
lcsVehicleNo : any
relationShipOfficerId : any
driverId : any
driverName : any
relationShipOfficerName : any
isActive : any
createdOn : any
createdBy : any
modifiedOn : any
modifyBy : any
locationId : any
createdById : any
modifyById : any
}
App.component.ts
ngOnInit() {
this.signalRService.startConnection();
this.signalRService.addTransferChartDataListener();
this.startHttpRequest();
}
我已从App.component中删除了Stackoverflow的其他方法
signal的nuget包
Signar的角度版本
我在浏览器控制台中收到此错误,但是当我在控制器上添加断点时,它仅一次完美地执行了该操作(您可以在控制台中看到响应)
下面是首次使用的GetAllVehicle的网络快照
下面是具有CORS问题的协商网络快照
我也尝试过this url,但一无所获。
您需要在中心上添加CORS,例如:
关于配置方法
app.UseCors(CorsPolicy);
关于AddAditionalServices
services.AddCors(options =>
{
options.AddPolicy(CorsPolicy, builder => builder.WithOrigins("http://localhost:4200")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()
.SetIsOriginAllowed((host) => true));
});
请注意,CORS方法的顺序很重要!
也不要使用@aspnet/signalr
程序包,因为它已被放弃并且已过时。您应该使用新的@microsoft/signalr
程序包,它还为您提供AutomaticReconnect
功能。