Blazor WASM API在Ubuntu上出现404异常,Windows环境正常求助
Blazor WASM API在Ubuntu服务器返回404错误排查指南
问题现象
Blazor WASM项目在Windows环境运行正常,但部署到Ubuntu Server 22.04后,请求GET http://**.**.**.**/api/files返回404 Not Found错误,错误信息为net_http_message_not_success_statuscode_reason, 404, Not Found。
服务器环境
- Ubuntu Server 22.04
- .NET 8 (8.0.100)
- Nginx 1.18.0
- MSSQL Server (16.0.4100.1-1 amd64)
项目结构
解决方案包含3个项目:Client、Server、Shared,Server为启动项目。
相关配置代码
Server项目Startup.cs
using BilirkisiRaporu.Server.Services; using Microsoft.AspNetCore.Localization; using System.Globalization; using System.Text.Json; using System.Text.Json.Serialization; namespace BilirkisiRaporu.Server { public class Startup { public IConfiguration Configuration { get; } public Startup(IConfiguration configuration) { Configuration = configuration; } public void ConfigureServices(IServiceCollection services) { services.AddLocalization(options => options.ResourcesPath = "Shared.Resources"); services.AddScoped<MahkemeDosyasiService>(); var connectionString = Configuration.GetConnectionString("SQLDbConnection"); services.AddDbContext<RaporDataContext>(options => options.UseSqlServer(connectionString)); services.AddControllers().AddJsonOptions(options => { options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve; options.JsonSerializerOptions.MaxDepth = 32; options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; }); services.AddHttpsRedirection(options => { options.HttpsPort = 443; }); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { var supportedCultures = new[] { new CultureInfo("en-US"), new CultureInfo("tr-TR") }; app.UseRequestLocalization(new RequestLocalizationOptions { DefaultRequestCulture = new RequestCulture("tr-TR"), SupportedCultures = supportedCultures, SupportedUICultures = supportedCultures }); } } }
Program.cs
global using BilirkisiRaporu.Server.Data; global using Microsoft.EntityFrameworkCore; using BilirkisiRaporu.Server; using Syncfusion.Blazor; var builder = WebApplication.CreateBuilder(args); Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense("****Licence here****"); builder.Services.AddSyncfusionBlazor(); var configuration = new ConfigurationBuilder() .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .Build(); var startup = new Startup(configuration); startup.ConfigureServices(builder.Services); builder.Services.AddControllersWithViews(); builder.Services.AddRazorPages(); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseWebAssemblyDebugging(); } else { app.UseExceptionHandler("/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseBlazorFrameworkFiles(); app.UseStaticFiles(); app.UseRouting(); app.MapRazorPages(); app.MapControllers(); app.MapFallbackToFile("index.html"); app.Run();
FilesController代码片段
using BilirkisiRaporu.Server.Services; using BilirkisiRaporu.Shared.DTOs; using BilirkisiRaporu.Shared.Models; using BilirkisiRaporu.Shared.ViewModels; using Microsoft.AspNetCore.Mvc; using System.Text.Json; using System.Text.Json.Serialization; namespace BilirkisiRaporu.Server.Controllers { [Route("api/[controller]")] [ApiController] public class FilesController : ControllerBase { private readonly FileDataContext _context; private readonly FileService _fileService; public FilesController(FileDataContext context, FileService fileService) { _context = context; _fileService = fileService; } [HttpGet] public IActionResult GetFilesAsJson() { .... } [HttpGet("{id}")] public async Task<IActionResult> GetFilesById(int id) { .... } [HttpPost("Create")] public async Task<ActionResult<Files>> CreateFiles(FilesViewModel viewModel) { .... } [HttpPut("Update")] public async Task<IActionResult> UpdateFiles([FromBody] FilesDTO updatedFile) { .... } .... } }
index.html相关部分
<head> .... <base href="/" /> .... </head>
组件初始化代码
protected override async Task OnInitializedAsync() { objRef = DotNetObjectReference.Create(this); filesDTOList = new List<filesDTO>(); try { var json = await Http.GetStringAsync("api/files"); var options = new JsonSerializerOptions { ReferenceHandler = ReferenceHandler.Preserve, PropertyNamingPolicy = JsonNamingPolicy.CamelCase, PropertyNameCaseInsensitive = true }; filesDTOList = JsonSerializer.Deserialize<List<filesDTO>>(json, options); filesDTOList = filesDTOList.OrderBy(item => item.Date).ToList(); } catch (Exception ex) { Console.WriteLine("An error occurred: " + ex.Message); } }
Server端systemd服务配置
[Unit] Description= Bilirkişi Raporu [Service] WorkingDirectory=/var/www/xyz ExecStart=/usr/bin/dotnet /var/www/xyz/BilirkisiRaporu.Server.dll Restart=always RestartSec=10 SyslogIdentifier=BilirkişiRaporu Environment=ASPNETCORE_ENVIRONMENT=Development [Install] WantedBy=multi-user.target
排查与解决步骤
1. 确认.NET服务状态
- 查看服务运行状态:
sudo systemctl status BilirkişiRaporu - 实时查看服务日志:
sudo journalctl -u BilirkişiRaporu -f,检查启动报错或异常信息 - 手动启动服务:
sudo systemctl start BilirkişiRaporu
2. 跳过Nginx直接验证API
.NET服务默认监听5000(HTTP)或7000(HTTPS)端口,在服务器上执行:curl http://localhost:5000/api/files
- 返回正常:问题出在Nginx配置
- 仍返回404:.NET服务未正确加载控制器或路由
3. 检查.NET路由与控制器
- 确认
Program.cs中已包含app.MapControllers();(你的代码已配置) - 检查
FilesController的[Route("api/[controller]")]和[HttpGet]属性无拼写错误 - 确认部署目录
/var/www/xyz下存在Controllers相关dll文件
4. 修复Nginx配置
创建或修改Nginx站点配置(/etc/nginx/sites-available/rapor.conf):
server { listen 80; server_name 你的服务器IP或域名; location / { 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 $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; } }
- 启用配置:
sudo ln -s /etc/nginx/sites-available/rapor.conf /etc/nginx/sites-enabled/ - 验证配置:
sudo nginx -t - 重启Nginx:
sudo systemctl restart nginx
5. 修复文件权限
确保.NET进程拥有部署目录的读写权限:
sudo chown -R www-data:www-data /var/www/xyz sudo chmod -R 755 /var/www/xyz
6. 检查配置与环境变量
- 确认
/var/www/xyz/appsettings.json中的连接字符串等配置正确 - 在systemd服务配置中添加端口绑定(可选):
重启服务生效。Environment=ASPNETCORE_URLS=http://0.0.0.0:5000
7. 启用详细日志排查
修改/var/www/xyz/appsettings.Development.json添加详细日志:
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Debug" } } }
重启服务后查看日志,分析路由匹配过程。
内容的提问来源于stack exchange,提问作者Tuna
相关产品推荐
相关产品推荐

