不允许在框架级别路由到最后一个子级未使用的路径



我有一个ASP.NET Core 3.1 MVC项目,我遇到了像这样的路由问题

  1. https://example.com/home/about
  2. https://example.com/home/about/nosuchpath

路由到同一控制器。

我希望第二个返回http 404错误。

目前,两者都在路由到家庭控制器并进行操作。

我已经阅读了下面的Microsoft路由指南,但没有发现任何关于禁止子路径的内容。

我目前的解决方案有点脏,用一个检查任何多余路线的属性来装饰控制器动作:

public class NoParamsValidatorAttribute : IAsyncActionFilter
{
public NoParamsValidatorAttribute()
{
}
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
if (ValidateIfAnyParams(context))
{
context.Result = new NotFoundResult();
}
else
{
await next();
}
}
private bool ValidateIfAnyParams(ActionExecutingContext context)
{
return (context?.ActionArguments?.Any() ?? false) || ((context?.RouteData?.Values?.Count ?? 0) > 2) || (context?.HttpContext?.Request?.QueryString.HasValue ?? false);
}
}

总的来说,我正在寻找一种可以作为一个整体应用的解决方案,而不依赖于单独装饰控制器动作,因为我有多个控制器动作面临相同的问题。

我有一个控制器,它有这样的操作,我想影响第一个,而不影响后面的方法参数。

// home/about/xxx should return httpstatus 404.
[HttpGet]
public IActionResult About()
{
return View();
}

// home/viewinfo/abc should not have an issue with this
[HttpGet]
public IActionResult ViewInfo(string info)
{
return View(info);
}

对于我的startup.cs,我很想明确指定端点,但对于多个控制器中的数百个控制器操作来说,这似乎是非常琐碎的。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime lifetime, ILoggerFactory loggerFactory, IConfiguration configuration, ILogger<Startup> logger)
{
// ...
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
// ...
}

在我看来,实现您的需求的最佳方式是将全局操作筛选器注册为您的NoParamstrack。

此全局操作筛选器将在请求转到实际操作之前激发,并在配置服务方法中注册。这不需要为每个控制器和操作设置它。

更多详细信息,您可以参考以下代码:

public class NoParamsValidator : IAsyncActionFilter
{
public NoParamsValidator()
{
}
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
if (ValidateIfAnyParams(context))
{
context.Result = new NotFoundResult();
}
else
{
await next();
}
}
private bool ValidateIfAnyParams(ActionExecutingContext context)
{
return (context?.ActionArguments?.Any() ?? false) || ((context?.RouteData?.Values?.Count ?? 0) > 2) || (context?.HttpContext?.Request?.QueryString.HasValue ?? false);
}
}

Startup.cs ConfigureServices添加以下代码:

services.AddControllersWithViews(options =>
{
options.Filters.Add(typeof(NoParamsValidator));
});

最新更新