You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React对接.NET后端CORS配置无效及数据提交失败求助

问题求助:React注册组件CORS错误+数据无法写入数据库

问题现象

  1. React注册页面提交时触发CORS错误,尝试多种CORS配置、axios/原生请求方式均无效
  2. 点击提交后,填写的用户数据未写入数据库

React注册组件代码

import axios from 'axios';
import { useState } from 'react';

const Registration = () => {
  const [formData, setFormData] = useState({
    userName: '',
    userEmail: '',
    userPhoneNumber: '',
    userAddress: '',
    userAge: 0,
    userGender: '',
    role: ''
  });

  const [error, setError] = useState(null);

  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormData({
      ...formData,
      [name]: name === 'userAge' ? Number(value) : value,
    });
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    try {
      const response = await axios.post('https://localhost:7094/api/User/Create', formData);
      console.log('Response data:', response.data);

      // 可在此处添加登录跳转或成功提示逻辑
    } catch (error) {
      console.error('请求失败:', error);
      setError(error.response?.data?.message || error.message);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      {error && <div style={{ color: 'red' }}>{error}</div>}
      <div>
        <label>UserName:</label>
        <input type="text" name="userName" value={formData.userName} onChange={handleChange} required />
      </div>
      <div>
        <label>Email:</label>
        <input type="email" name="userEmail" value={formData.userEmail} onChange={handleChange} required />
      </div>
      <div>
        <label>Phone Number:</label>
        <input type="text" name="userPhoneNumber" value={formData.userPhoneNumber} onChange={handleChange} />
      </div>
      <div>
        <label>Address:</label>
        <input type="text" name="userAddress" value={formData.userAddress} onChange={handleChange} />
      </div>
      <div>
        <label>Age:</label>
        <input type="number" name="userAge" value={formData.userAge} onChange={handleChange} />
      </div>
      <div>
        <label>Gender:</label>
        <input type="text" name="userGender" value={formData.userGender} onChange={handleChange} />
      </div>
      <div>
        <label>Role (用户或管理员):</label>
        <input type="text" name="role" value={formData.role} onChange={handleChange} required />
      </div>
      <button type="submit">Submit</button>
    </form>
  );
};

export default Registration;

页面错误信息

页面显示的CORS错误信息

.NET后端Program.cs代码

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using System.Text;
using TrainTicket.Interfaces;
using TrainTicket.Models;
using TrainTicket.Repository;

var builder = WebApplication.CreateBuilder(args);

var corsOrigins = new string[] { "http://localhost:5173" };

builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowAll",
        policy =>
        {
            policy.WithOrigins(corsOrigins)
                .AllowAnyMethod()
                .AllowAnyHeader()
                .AllowCredentials();
        });
});

builder.Services.AddControllers();
builder.Services.AddHttpContextAccessor();
builder.Services.AddAutoMapper(typeof(Program));

builder.Services.AddDbContext<ReservationDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddScoped<IUserLoginInterface, UserLoginRepository>();
builder.Services.AddScoped<IUserInterface, UserRepository>();
builder.Services.AddScoped<IAdminLoginInterface, AdminLoginRepository>();
builder.Services.AddScoped<ITrainDetailsInterface, TrainDetailsRepository>();
builder.Services.AddScoped<ISeatDetailsInterface, SeatDetailsRepository>();
builder.Services.AddScoped<ISearchDetailsInterface, SearchDetailsRepository>();
builder.Services.AddScoped<IEmailSenderInterface, EmailSenderRepository>();

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidIssuer = builder.Configuration["Jwt:Issuer"],
        ValidAudience = builder.Configuration["Jwt:Audience"],
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])),
        ClockSkew = TimeSpan.Zero
    };
});

builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new() { Title = "TrainTicket API", Version = "v1" });
    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Description = "JWT Authorization header using the Bearer scheme",
        Type = SecuritySchemeType.Http,
        Scheme = "bearer"
    });
    c.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference
                {
                    Type = ReferenceType.SecurityScheme,
                    Id = "Bearer"
                }
            },
            Array.Empty<string>()
        }
    });
});

var app = builder.Build();

app.UseCors("AllowAll");
app.UseAuthentication();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "TrainTicket API v1"));
}

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();

核心需求

注册页面收集userName、userEmail、PhoneNumber、Address、Age、Gender、Role(用户/管理员),userId和密码自动生成,提交后数据需写入数据库。


解决方案

1. 修复React组件基础问题

  • 补全useState导入:原代码未导入React核心Hook,导致组件无法正常渲染
  • 添加role字段:原formData未包含role属性,导致前端输入的角色无法传递到后端
  • 修正axios请求处理:axios返回的response已自动解析JSON,无需额外调用response.json()
  • 类型转换处理:将userAge从字符串转为数字,避免后端类型不匹配

2. 解决CORS问题

当前配置逻辑正确,需排查以下点:

  • 确认前端端口:确保前端运行在http://localhost:5173,若端口不符则修改corsOrigins数组
  • 简化CORS配置:若前端未发送Cookie,可移除.AllowCredentials(),减少校验复杂度
  • 中间件顺序:确保UseCors在UseAuthorization和UseHttpsRedirection之前(当前顺序已符合要求)
  • 直接测试API:用Postman调用https://localhost:7094/api/User/Create,确认接口本身可正常写入数据

3. 后端接口关键修复

  • 允许匿名访问注册接口:注册接口无需JWT认证,需添加[AllowAnonymous]特性,避免被认证拦截
    [ApiController]
    [Route("api/[controller]")]
    public class UserController : ControllerBase
    {
        private readonly IUserInterface _userRepo;
    
        public UserController(IUserInterface userRepo)
        {
            _userRepo = userRepo;
        }
    
        [HttpPost("Create")]
        [AllowAnonymous]
        public async Task<IActionResult> CreateUser(UserDto userDto)
        {
            var user = new User
            {
                UserName = userDto.UserName,
                UserEmail = userDto.UserEmail,
                UserPhoneNumber = userDto.UserPhoneNumber,
                UserAddress = userDto.UserAddress,
                UserAge = userDto.UserAge,
                UserGender = userDto.UserGender,
                Role = userDto.Role,
                UserId = Guid.NewGuid().ToString(),
                Password = GenerateRandomPassword()
            };
    
            await _userRepo.CreateUser(user);
            return Ok(new { UserId = user.UserId, Password = user.Password });
        }
    
        private string GenerateRandomPassword()
        {
            var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
            var random = new Random();
            return new string(Enumerable.Repeat(chars, 8).Select(s => s[random.Next(s.Length)]).ToArray());
        }
    }
    
  • 确认Repository写入逻辑:确保UserRepository正确执行添加和保存操作
    public class UserRepository : IUserInterface
    {
        private readonly ReservationDbContext _context;
    
        public UserRepository(ReservationDbContext context)
        {
            _context = context;
        }
    
        public async Task CreateUser(User user)
        {
            _context.Users.Add(user);
            await _context.SaveChangesAsync();
        }
    }
    
  • 字段名映射检查:确保前端字段名(如userName)与后端模型字段名(如UserName)符合ASP.NET Core驼峰命名自动映射规则

4. 调试建议

  • 前端调试:查看浏览器Network面板,检查请求状态码、请求头、请求体是否正确
  • 后端调试:在CreateUser方法设置断点,确认是否接收到前端数据,写入过程是否有异常
  • 日志排查:添加后端日志记录请求细节和错误信息,快速定位问题

内容的提问来源于stack exchange,提问作者whizzx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 21:35:53