I have an api running on localhost:5001, in my ASP.NET MVC application I was able to do this:
routes.MapRoute(
name: "Default",
url: "{*stuff}",
defaults: new { controller = "Default", action = "DefaultAction" }
);
this meant that i could simply type localhost:5001/aRandomStuff in my webbrowser and "aRandomStuff
" would get passed in as a parameter in my actionresult DefaultAction
inside my DefaultController
.
What is the equivalence of doing this kind of routing in .net5 under
app.UseEndpoints(endpoints =>
{
//routing here
});
?
CodePudding user response:
You could use the RouteAttribute
directly on your endpoint.
Just map your default controller in your Startup.cs
(if you need to have a default controller):
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
Then in your controller add the Route
attribute on the action you want.:
[Route("{id}")]
public IActionResult DefaultAction(string id)
{
return View();
}
Since only the endpoint has a parameter {} route defined in this case and the controller doesn't, the above endpoint will be triggered from localhost:5001/whateverString and whateverString will be sent in as a value to the parameter id
.
I needed to edit my original answer since it was meant for Api Endpoints. The edited answer should work for your MVC app instead.
CodePudding user response:
They made many updates to routing in .Net 5 that really messed with how we perceive catch-all routing. These were actually intentional and technically how they want it to work. However, it introduced a lot of confusion from the POV from most of us. You can see some discussion and bug logs here, here, and here.
I have not been able to get it to work with UseEndpoints in startup. As the first link shows, the order of the controllers for precendence is also messing with things, and the other answers here could potentially cause route conflicts or other confusion for which route is most important.
The only way I have seen this to work is with route attributes in the controller where we set the order. This means that you know it will be the last pattern checked:
[Route("{*url}", Order = 999)]
public IActionResult MyCatchAll(string url)
{
...
}
This way the priority order will be last (I think most are between 0-5, so 999 is plenty high) and the url is passed as a parameter for you to manage as needed. And frankly, I prefer this but the option to do either would be nice.
If someone has a way to do this in app.UseEndpoints, I would love to see it, but all the samples fail or only work sporadically for me.
CodePudding user response:
Use This Pattern on Your Action And Catch All Request And Get First Route Value Like This
[Route("/{**catchAll}")]
public IActionResult Index()
{
string randomQuery =HttpContext.Request.RouteValues["catchAll"]?.ToString();
return Content(randomQuery);
}
CodePudding user response:
In the following code the DefaultAction()
method uses the Route
attribute with the regular expression. All URL's with the following format localhost:port/SomeStringStuff
will be processed by this action method.
[ApiController]
[Route("[controller]")]
public class DefaultController : ControllerBase
{
[HttpGet]
[Route(@"/{text:regex(.*Stuff$)}")]
public string DefaultAction(string text)
{
/// your code ...
return text;
}
}
Take to account that the ASP.NET Core framework adds RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant
to the regular expression constructor.
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});