在Blazor Server应用中配置路由,让.json/.js文件由控制器处理
解决Blazor Server中带扩展名文件请求由控制器处理的问题
我之前在做Blazor Server项目时也遇到过一模一样的问题——带扩展名的请求(比如.json/.js)会被静态文件中间件优先拦截,根本到不了控制器。核心原因是Blazor Server的默认中间件顺序里,StaticFiles会先处理所有有已知扩展名的请求,跳过后续的端点路由。下面给你几个经过验证的解决方案:
方案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; } } });
- 编写对应的控制器,匹配这些请求:
[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(); } }
- 确保控制器端点注册在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
相关产品推荐
相关产品推荐

