.NET 8 Blazor自动渲染项目样式表被识别为parent参数问题
问题原因
当浏览器请求自动生成的样式表[project].styles.css时,Blazor路由会按你定义的顺序依次匹配规则。由于/{parent?}路由规则过于宽泛(接受任意可选字符串作为parent参数),且ASP.NET Core静态文件中间件未在Blazor路由前优先拦截该请求,导致[project].styles.css被识别为parent参数值,触发页面OnParametersSetAsync()逻辑后引发异常。
修复方法
方法一:给路由参数添加正则约束,过滤静态资源路径
修改路由模板,给所有字符串类型的可选参数添加正则约束,限制参数值不能包含小数点(静态资源文件名通常带后缀,如.css),避免静态资源路径被匹配:
@page "/" @page "/{parent:regex(^[^.]+$)?}" @page "/{parent:regex(^[^.]+$)?}/{categoryUrl:regex(^[^.]+$)?}" @page "/{parent:regex(^[^.]+$)?}/{categoryUrl:regex(^[^.]+$)?}/{url:regex(^[^.]+$)?}" @page "/{parent:regex(^[^.]+$)?}/{categoryUrl:regex(^[^.]+$)?}/{url:regex(^[^.]+$)?}/{pId:regex(^[^.]+$)?}" @page "/{parent:regex(^[^.]+$)?}/{categoryUrl:regex(^[^.]+$)?}/{url:regex(^[^.]+$)?}/{suburl:regex(^[^.]+$)?}/{pId:regex(^[^.]+$)?}" @page "/{parent:regex(^[^.]+$)?}/{categoryUrl:regex(^[^.]+$)?}/{url:regex(^[^.]+$)?}/{pId:regex(^[^.]+$)?}/{month:int?}/{year:int?}" @rendermode InteractiveAuto
正则^[^.]+$表示参数值不能包含小数点,直接过滤带后缀的静态资源路径。
方法二:调整中间件顺序,确保静态资源优先处理
在Program.cs中,先注册静态文件中间件,再通过MapWhen限制Blazor路由仅处理非静态资源请求:
var builder = WebApplication.CreateBuilder(args); // 注册所需服务... var app = builder.Build(); // 优先处理静态资源请求 app.UseStaticFiles(); // 仅对非静态资源路径启用Blazor路由 app.MapWhen(context => { var path = context.Request.Path.Value; return !path.StartsWith("/_content") && !path.EndsWith(".css") && !path.EndsWith(".js") && !path.EndsWith(".png") && !path.EndsWith(".jpg") && path != "/favicon.ico"; }, blazorApp => { blazorApp.MapRazorComponents<App>() .AddInteractiveWebAssemblyRenderMode() .AddInteractiveServerRenderMode() .AddAdditionalAssemblies(typeof(Client._Imports).Assembly); }); app.Run();
这样静态资源请求会被UseStaticFiles直接处理,不会进入Blazor路由匹配流程。
方法三:自定义路由约定,批量排除静态资源
通过自定义路由约定,让Blazor自动排除常见静态资源路径:
// 在Program.cs的服务注册环节添加 builder.Services.AddRazorComponents() .AddInteractiveWebAssemblyRenderMode() .AddInteractiveServerRenderMode() .AddRoutingConvention<StaticResourceExclusionConvention>(); // 自定义路由约定类 public class StaticResourceExclusionConvention : IComponentApplicationModelConvention { private readonly HashSet<string> _excludedSuffixes = new() { ".css", ".js", ".png", ".jpg" }; public void Apply(ComponentApplicationModel model) { foreach (var selector in model.Selectors.ToList()) { if (selector.AttributeRouteModel.Template.Contains("?")) { selector.AttributeRouteModel.ConstraintMap.Add("excludeStatic", new StaticResourceConstraint(_excludedSuffixes)); } } } } // 自定义路由约束类 public class StaticResourceConstraint : IRouteConstraint { private readonly HashSet<string> _excludedSuffixes; public StaticResourceConstraint(HashSet<string> excludedSuffixes) { _excludedSuffixes = excludedSuffixes; } public bool Match(HttpContext? httpContext, IRouter? route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection) { if (values.TryGetValue(routeKey, out var value) && value is string strValue) { return !_excludedSuffixes.Any(suffix => strValue.EndsWith(suffix, StringComparison.OrdinalIgnoreCase)); } return true; } }
之后在路由模板中使用该约束,比如@page "/{parent:excludeStatic?}",即可自动排除静态资源路径。
内容的提问来源于stack exchange,提问作者Pettanord
相关产品推荐
相关产品推荐

