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

ASP.NET Core React SPA中Customer接口POST请求404问题求助

问题:ASP.NET Core API POST /api/Customer 返回404错误

我正在用React.js开发ASP.NET Core单页应用,调用Customer相关POST接口时遇到404 Not Found(无匹配路由)错误。已经用Postman测试过对应数据,还是没找到问题。我对这套技术经验不足,如有遗漏信息或需要查看更多代码,请告知,谢谢帮助!

CustomerController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using KCA.Core.Exceptions;
using KCA.Core.Interfaces;
using KCA.Core.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace KCA.WebApi.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class CustomerController : ControllerBase
    {
        private readonly ICustomerServices _customerServices;

        public CustomerController(ICustomerServices customerServices)
        {
            _customerServices = customerServices;
        }

        // GET: api/Customer
        [HttpGet]
        public async Task<ActionResult<IEnumerable<Customer>>> GetCustomers()
        {
            try
            {
                var customers = await _customerServices.GetAllAsync();
                return Ok(customers);
            }
            catch (Exception ex)
            {
                return StatusCode(StatusCodes.Status500InternalServerError, ex.Message);
            }
        }

        // GET: api/Customer/{id}
        [HttpGet("{id}")]
        public async Task<ActionResult<Customer>> GetCustomer(Guid id)
        {
            try
            {
                var customer = await _customerServices.GetByIdAsync(id);
                return Ok(customer);
            }
            catch (NotFoundException ex)
            {
                return NotFound(ex.Message);
            }
            catch (BadRequestException ex)
            {
                return BadRequest(ex.Message);
            }
            catch (Exception ex)
            {
                return StatusCode(StatusCodes.Status500InternalServerError, ex.Message);
            }
        }

        // POST: api/Customer
        [HttpPost]
        public async Task<ActionResult<Customer>> PostCustomer([FromBody] Customer customer)
        {
            try
            {
                await _customerServices.AddAsync(customer);
                return CreatedAtAction(nameof(GetCustomer), new { id = customer.Id }, customer);
            }
            catch (BadRequestException ex)
            {
                return BadRequest(ex.Message);
            }
            catch (ConflictException<Customer> ex)
            {
                return Conflict(ex.Message);
            }
            catch (Exception ex)
            {
                return StatusCode(StatusCodes.Status500InternalServerError, ex.Message);
            }
        }

        // PUT: api/Customer/{id}
        [HttpPut("{id}")]
        public async Task<IActionResult> PutCustomer(Guid id, [FromBody] Customer customer)
        {
            if (id != customer.Id)
            {
                return BadRequest("Customer ID mismatch.");
            }

            try
            {
                await _customerServices.UpdateAsync(customer);
                return NoContent();
            }
            catch (NotFoundException ex)
            {
                return NotFound(ex.Message);
            }
            catch (BadRequestException ex)
            {
                return BadRequest(ex.Message);
            }
            catch (Exception ex)
            {
                return StatusCode(StatusCodes.Status500InternalServerError, ex.Message);
            }
        }

        // DELETE: api/Customer/{id}
        [HttpDelete("{id}")]
        public async Task<IActionResult> DeleteCustomer(Guid id)
        {
            try
            {
                await _customerServices.DeleteAsync(id);
                return NoContent();
            }
            catch (NotFoundException ex)
            {
                return NotFound(ex.Message);
            }
            catch (BadRequestException ex)
            {
                return BadRequest(ex.Message);
            }
            catch (Exception ex)
            {
                return StatusCode(StatusCodes.Status500InternalServerError, ex.Message);
            }
        }
    }
}

Program.cs(含Startup类)

using KCA.Infrastructure;
using KCA.Core.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using KCA.Infrastructure.Data;
using KCA.Core.Interfaces;
using KCA.Core.Services;

namespace KCA.Web
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }

    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)
        {
            var connectionString = Configuration.GetConnectionString("DefaultConnection");
            services.AddDbContext<KCAContext>(options =>
                options.UseSqlServer(connectionString));
            services.AddDatabaseDeveloperPageExceptionFilter();

            services.AddDefaultIdentity<Employee>(options => options.SignIn.RequireConfirmedAccount = false)
                .AddEntityFrameworkStores<KCAContext>()
                .AddDefaultTokenProviders();

            services.AddIdentityServer()
                .AddApiAuthorization<Employee, KCAContext>();

            //Add Services
            services.AddScoped<IKCAContext, KCAContext>();
            services.AddScoped<ICarService, CarServices>();
            services.AddScoped<ICustomerServices, CustomerServices>();
            services.AddScoped<IEmployeeServices, EmployeeServices>();
            services.AddScoped<IPartsService, PartsService>();
            services.AddScoped<IJobServices, JobServices>();

            // Add CORS policy
            services.AddCors(options =>
            {
                options.AddPolicy("AllowAll", builder =>
                {
                    builder.AllowAnyOrigin()
                           .AllowAnyMethod()
                           .AllowAnyHeader();
                });
            });

            services.AddControllersWithViews();
            services.AddRazorPages();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseMigrationsEndPoint();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthentication();
            app.UseIdentityServer();
            app.UseAuthorization();

            app.UseCors("AllowAll");

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                     name: "default",
                    pattern: "{controller}/{action=Index}/{id?}");
                endpoints.MapRazorPages();
                endpoints.MapFallbackToFile("index.html");
            });
        }
    }
}

Postman请求信息

我在Postman中使用以下请求测试,仍返回404:

POST https://localhost:44401//api/Customer
Body: (JSON)
{
    "Id": "b63da63d-5fd5-4b5f-8e33-4d4e7c9db927",
    "FirstName": "John",
    "LastName": "Doe",
    "ContactNumber": "555-123-4567",
    "Email": "john.doe@example.com",
    "Address": "123 Main St",
    "Postcode": "12345"
}

Customer模型

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace KCA.Core.Models
{
    public class Customer
    {
        public Guid Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        [Phone]
        public string ContactNumber { get; set; }
        [EmailAddress]
        public string Email { get; set; }
        public string Address { get; set; }
        public string Postcode { get; set; }

        //Relational data
        public virtual ICollection<Car> Cars { get; set; }
        public virtual ICollection<Job> Jobs { get; set; }
    }
}

排查与解决方案

  1. 修正请求URL的多余斜杠
    你当前的请求URL是https://localhost:44401//api/Customer,域名与api之间多了一个斜杠,这会导致路由匹配失败。将URL改为https://localhost:44401/api/Customer后重试。

  2. 确保API控制器路由被正确注册
    在Startup.ConfigureServices中,当前仅调用了services.AddControllersWithViews(),建议添加services.AddControllers()明确注册API控制器服务,确保框架能扫描到CustomerController:

    services.AddControllers(); // 添加这一行
    services.AddControllersWithViews();
    services.AddRazorPages();
    
  3. 调整路由匹配顺序
    在Startup.Configure的UseEndpoints中,API控制器路由应优先于SPA fallback规则,避免API请求被误拦截。修改为:

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers(); // 优先处理API路由
        endpoints.MapControllerRoute(
             name: "default",
            pattern: "{controller}/{action=Index}/{id?}");
        endpoints.MapRazorPages();
        endpoints.MapFallbackToFile("index.html");
    });
    
  4. 验证控制器程序集扫描
    如果CustomerController所在的KCA.WebApi是独立类库,需要在AddControllers中指定程序集,确保框架能发现该控制器:

    services.AddControllers()
        .AddApplicationPart(typeof(KCA.WebApi.Controllers.CustomerController).Assembly);
    
  5. 检查端口是否正确
    确认Postman中使用的端口44401与ASP.NET Core项目启动时的HTTPS端口一致,可以在项目属性的“调试”选项卡中查看实际端口。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 16:46:59