У меня возникла проблема с обменом данными из веб-приложения Angular 9 UI. Я знаю множество тем в этой области, но я не могу заставить это работать, я поделюсь с вами своим кодом, чтобы посмотреть, смогу ли я туда добраться. Кажется, я не могу найти причину root, если это ошибка конфигурации. Net API, NGINX или приложение Angular. Это мое первое «реальное» решение, поэтому я все еще изучаю все компоненты.
У меня есть один контроллер. Net 3.1 API, предоставляющий данные MySQL Db. Приложение Angular находится за развертыванием прокси-сервера NGIX.
Запросы GET, PUT, POST, DELETE работают из приложения Postman или при переходе к адресу контроллера. Также запрос GET работает в приложении Angular. Однако запросы PUT, POST не работают.
Я безуспешно пытался изменить конфигурацию запуска. NET API, добавив пакет CORS Nugget от Microsoft, следуя их руководству. После этого GET тоже перестает работать. Ошибка в приложении Angular при выполнении запроса PUT / POST:
Доступ к XMLHttpRequest в 'http://192.168.10.40/api/AlertsConfig/' from origin 'http://localhost: 4200 'заблокирован политикой CORS: ответ на предварительный запрос не проходит проверку контроля доступа: на запрошенном ресурсе отсутствует заголовок' Access-Control-Allow-Origin '.
What Я пробовал:
public void ConfigureServices(IServiceCollection services)
{
// ...
// Add CORS policy
services.AddCors(options =>
{
options.AddPolicy("test",
builder =>
{
// Not a permanent solution, but just trying to isolate the problem
builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();
});
});
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
// Use the CORS policy
app.UseCors("test");
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
My. Net Controller - Для упрощения меня просто интересует PUT
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using BeckerSmartFan.Data;
using BeckerSmartFan.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace BeckerSmartFan.Controllers
{
[Route("api/[controller]")]
[ApiController]
[AllowAnonymous]
public class AlertsConfigController : ControllerBase
{
private readonly ConnectionStrings con;
private readonly Data.MySqlConnector mySqlConnector;
public AlertsConfigController(ConnectionStrings c)
{
con = c;
mySqlConnector = new Data.MySqlConnector();
}
// GET: api/AlertsConfig
[HttpGet]
public async Task<IActionResult> Get([FromQuery] IEnumerable<AlertsConfig> alertsConfigs, [FromQuery] string type)
{
return await Task.Run(() =>
{
var listAlertConfigs = mySqlConnector.GetAllAlertsConfigs(con, type);
return listAlertConfigs != null ? (IActionResult)Ok(listAlertConfigs) : NotFound();
});
}
// PUT: api/AlertsConfig/
[HttpPut]
public async Task<IActionResult> Put([FromBody] AlertsConfig alertConfig)
{
return await Task.Run(() =>
{
var result = mySqlConnector.UpdateAlertConfig(con, alertConfig);
return result > 0 ? (IActionResult)Ok(alertConfig) : BadRequest();
});
}
}
}
My Angular Http Service :
import { HttpClient, HttpErrorResponse, HttpParams } from '@angular/common/http';
import { catchError, map, timeout } from 'rxjs/operators';
import { throwError } from 'rxjs';
import { NotFoundError } from '../common/not-found-error';
import { FanDataTag } from './FanDataTag';
const QueryTimeOut : number = 5000;
export class ApiDataService {
constructor(private url: string, private http: HttpClient) {
console.log("Contstructor:" + url);
}
getAll(startDate?:string, endDate?:string){
if(typeof startDate === 'undefined' && typeof endDate === 'undefined')
{
return this.http.
get<any[]>
(
this.url
)
.pipe
(
catchError
(
this.handleError
)
,
timeout
(
QueryTimeOut
)
);
}
else
{
return this.http
.get<any[]>
(
this.url,
{
params:
{
dateStart:startDate,
dateEnd: endDate
}
}
)
.pipe
(
catchError
(
this.handleError
),
timeout(
QueryTimeOut
)
);
}
}
getAlertsConfig(type?:string){
if(typeof type === 'undefined')
{
return this.http.
get<any[]>
(
this.url
)
.pipe
(
catchError
(
this.handleError
)
,
timeout
(
QueryTimeOut
)
);
}
else
{
return this.http
.get<any[]>
(
this.url,
{
params:
{
type:type
}
}
)
.pipe
(
catchError
(
this.handleError
),
timeout(
QueryTimeOut
)
);
}
}
getLastRecord(getLastRecord?:boolean)
{
return this.http.get<any[]>(this.url, { params:{
dateStart:null,
dateEnd: null, getLastRecord: getLastRecord.toString()} }).pipe(timeout(QueryTimeOut));
}
getRecord(recordId?:number)
{
return this.http.get<any[]>(this.url + "/" + recordId).pipe(timeout(QueryTimeOut));;
}
create(resource: any){
return this.http.post<any>(this.url , JSON.stringify(resource))
.pipe(
catchError(this.handleError));
}
update(resource:any, isPatch:boolean)
{
if(isPatch)
{
return this.http.patch(this.url, JSON.stringify({isRead:true}))
.pipe(
catchError(this.handleError));
}
else
{
return this.http.put(this.url, resource );
}
}
delete(id: number){
return this.http.delete(this.url+"/"+id)
.pipe(
catchError(this.handleError));
}
private handleError(error: HttpErrorResponse) {
console.log(error);
if (error.error instanceof NotFoundError) {
// A client-side or network error occurred. Handle it accordingly.
return throwError(
'Bad request. Please refresh your page, and try again.');
}
else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
return throwError(
error.statusText + ": " + error.name );
}
};
}
NGINX Конфигурация:
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/WebApp;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name _;
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Content-Type,Accept';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
proxy_pass http://localhost:5000/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /api/FanDataTags {
proxy_pass http://localhost:5000/api/FanDataTags;
}
location /api/AlertsConfig {
proxy_pass http://localhost:5000/api/AlertsConfig;
}
server {
listen 8080;
listen [::]:8080;
server_name _;
root /var/www/Angular;
location / {
#directory, then fall back to displaying a 404.
try_files $uri $uri/ /index.html;
index index.html index.htm;
#proxy_pass http://localhost:8080/;
#proxy_http_version 1.1;
#proxy_set_header Upgrade $http_upgrade;
#proxy_set_header Connection keep-alive;
#proxy_set_header Host $host;
#proxy_cache_bypass $http_upgrade;
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#proxy_set_header X-Forwarded-Proto $scheme;
}
}
Вкладка «Сеть» в Chrome: