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

在Blazor Server应用中配置路由,让.json/.js文件由控制器处理

解决Blazor Server中带扩展名文件请求由控制器处理的问题

我之前在做Blazor Server项目时也遇到过一模一样的问题——带扩展名的请求(比如.json/.js)会被静态文件中间件优先拦截,根本到不了控制器。核心原因是Blazor Server的默认中间件顺序里,StaticFiles会先处理所有有已知扩展名的请求,跳过后续的端点路由。下面给你几个经过验证的解决方案:

方案1:调整静态文件中间件,排除特定扩展名

这个方法直接修改静态文件处理规则,让指定扩展名的请求跳过静态文件中间件,转由控制器处理:

  1. 在Program.cs中,替换默认的app.UseStaticFiles()为带配置的版本:
app.UseStaticFiles(new StaticFileOptions
{
    OnPrepareResponse = ctx =>
    {
        var requestPath = ctx.Context.Request.Path.Value;
        // 拦截.json和.js扩展名的请求
        if (requestPath.EndsWith(".json", StringComparison.OrdinalIgnoreCase) ||
            requestPath.EndsWith(".js", StringComparison.OrdinalIgnoreCase))
        {
            // 标记为404,让后续中间件(控制器)接管处理
            ctx.Context.Response.StatusCode = StatusCodes.Status404NotFound;
            ctx.Context.Response.ContentLength = 0;
            ctx.Context.Response.Body = Stream.Null;
        }
    }
});
  1. 编写对应的控制器,匹配这些请求:
[ApiController]
[Route("{filename}.json")] // 匹配如/test.json的请求
public class JsonFileController : ControllerBase
{
    [HttpGet]
    public IActionResult GetJsonFile(string filename)
    {
        // 拼接根目录下的文件路径
        var fullPath = Path.Combine(Directory.GetCurrentDirectory(), $"{filename}.json");
        
        // 安全检查:防止路径遍历攻击
        if (!fullPath.StartsWith(Directory.GetCurrentDirectory(), StringComparison.OrdinalIgnoreCase))
        {
            return Forbid();
        }

        if (System.IO.File.Exists(fullPath))
        {
            return PhysicalFile(fullPath, "application/json");
        }
        return NotFound();
    }
}
  1. 确保控制器端点注册在Blazor回退路由之前:
// 先注册控制器路由
app.MapControllers();
// 再注册Blazor相关端点
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

方案2:用MapWhen精准拦截特定请求

如果不想修改全局静态文件配置,这个方法更灵活——直接把指定扩展名的请求单独导向控制器:

在Program.cs中,在UseStaticFiles之前添加MapWhen分支:

// 拦截所有带.json或.js扩展名的请求
app.MapWhen(context => 
    context.Request.Path.Value.EndsWith(".json", StringComparison.OrdinalIgnoreCase) ||
    context.Request.Path.Value.EndsWith(".js", StringComparison.OrdinalIgnoreCase), 
    appBuilder =>
    {
        appBuilder.UseRouting();
        appBuilder.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers(); // 让这些请求直接走控制器
        });
    });

// 继续原来的中间件流程
app.UseStaticFiles();
app.UseBlazorFrameworkFiles();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

这种方式下,符合条件的请求会被单独路由到控制器,不影响其他静态文件的正常访问。

方案3:移除特定扩展名的静态文件映射

通过移除静态文件中间件对.json/.js的扩展名映射,让它无法识别这些文件类型,从而交给后续控制器处理:

// 创建自定义的内容类型提供器
var contentTypeProvider = new FileExtensionContentTypeProvider();
// 移除.json和.js的默认映射
contentTypeProvider.Mappings.Remove(".json");
contentTypeProvider.Mappings.Remove(".js");

// 使用自定义配置的静态文件中间件
app.UseStaticFiles(new StaticFileOptions
{
    ContentTypeProvider = contentTypeProvider,
    ServeUnknownFileTypes = false // 未知类型返回404,交给控制器处理
});

同样需要确保app.MapControllers()在Blazor端点之前注册。

关键注意事项

  • 安全第一:一定要添加路径遍历检查,防止恶意请求访问服务器上的敏感文件(比如../../secret.json)。
  • 路径大小写:使用StringComparison.OrdinalIgnoreCase处理大小写问题,避免TEST.JSON这类请求被遗漏。
  • 保留合法静态文件:如果你的wwwroot目录下有需要正常访问的.json/.js文件,可以在逻辑中排除/wwwroot/开头的路径。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 18:58:00