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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 13:15:53