I have this possible urls:
mywebsite/a/b/c.txt
mywebsite/x/t
mywebsite/z
mywebsite/z/i.jpg
So when the url ends with a file, I need to return 404, otherwise I call the controller. To this I have
endpoints.MapControllerRoute(
name: "default",
pattern: "{*.}",
defaults: new { controller = "Home", action = "Index" });
And this how I'm trying to check for router files
// endpoints.MapGet("{file:regex(.(css|txt|js|jpg|png|ico|json)$)}", async context =>
// endpoints.MapGet(@"(.*\.)(jpe?g|css|txt|js|png|ico|json)$", async context =>
/* endpoints.MapGet(@"{file:regex((.*\.)(jpe?g|css|txt|js|png|ico|json)$)}", async context =>
{
context.Response.StatusCode = 404;
}); */
endpoints.MapControllerRoute(
name: "File",
// pattern: @"(.*\.)(jpe?g|css|txt|js|png|ico|json)$",
// pattern: @"{controller:(.*\.)(jpe?g|css|txt|js|png|ico|json)$}",
// pattern: "{ssn}",
// constraints: new { ssn = @"(.*\.)(jpe?g|css|txt|js|png|ico|json)$" },
pattern: @".*\.(css|js|gif|jpg)(/.)?",
defaults: new { controller = "NotFound", action = "Index" });
The problem is that https://localhost:5001/style.css works, but https://localhost:5001/z/style.css it doesn't.
So what could I be missing here?
You cannot use the
catch-allnotation (expressed by{*...}or{**...}) to solve this issue. It does not support that way because the catch-all will match everything to the end of the path. The name following*is the route data key which can be used to get the captured value in your code later.To solve this, you can use a middleware for this purpose. The route is mapped normally to some of your patterns. But later in the processing pipeline, we can examine the
Request.Pathto accordingly modify the `Request.Path (like URL rewriting), like this:The above code must be placed before
app.UseStaticFiles, otherwise the static files middleware will handle and short-circuit the requests first.Note that
LinkGenerator.GetPathByActioncan returnnullif the controller or action does not exist. So in that case we fallback to the default conventional path of/NotFound.