Route Name for Conventions-Based Routing - asp.net-core

I am using conventions-based routing (as opposed to attribute-based routing) using ASP.NET CORE 3. I know it is possible to get the chosen route name when using attribute-based routing by using the AttributeRouteInfo.Name property. How do I do the same when using conventions-based routing (by this I mean setting up the routes in Startup.cs)? I can't find any explanation or properties.

The way I found to do it is like this, and it works with both attribute routing and conventional routing. Put this in the controller's action method:
Endpoint endpoint = ControllerContext.HttpContext.Features.Get<IEndpointFeature>()?.Endpoint;
String routeName = endpoint?.Metadata.GetMetadata<RouteNameMetadata>().RouteName;
This technique does not require you to add custom objects to the MapControllerRoute() as in Zhi Lv's approach.

From your description, I assume your application is an Asp.net Core MVC application, and in the Startup.Configure method, you are using the MapControllerRoute() or MapAreaControllerRoute() method to set the conventional route, like this:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
And at present, you want to get the route name ("default") in the controller method, right?
If that is the case, as a workaround, you could use the MapControllerRoute() and MapAreaControllerRoute() method's defaults parameter to store the route name.
For example:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default route",
pattern: "{controller=Reports}/{action=Index}/{id?}",
new { routeName= "default route" }); //add the routeName.
endpoints.MapRazorPages();
});
Then, in the controller method, you could get the value from the ControllerContext.RouteData, like this:
public IActionResult Index()
{
var contenxt = ControllerContext.RouteData.Values;
if (contenxt.Keys.Contains("routeName"))
{
var routename = contenxt["routeName"];
}
return View();
}
The screenshot as below:

Related

.NET CORE incorrect controller routing

I have a problem with controller actions not returning views. They are looking in the wrong area.
I'm new to core but I've tried to read up online for material and I'm seeing a lot of Global.asax.cs, App_Start files etc that I'm not seeing in my created project.
My problem is:
I created a project, implemented Areas like so:
As an example, in CommonController (which has 'Area("Common") area annotation) I have a return view method
public ActionResult RoadMap()
{
return View();
}
With the actionlink of:
#Html.ActionLink("Roadmap", "RoadMap", "Common")</span>
But when I access the link, it tries to look in "https://localhost:44325/Home/Common/RoadMap"
My startup code contains:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "Account",
pattern: "{area:exists}/{controller=Account}/{action}/{id?}");
endpoints.MapControllerRoute(
name: "Common",
pattern: "{area:exists}/{controller=Common}/{action}/{id?}");
endpoints.MapControllerRoute(
name: "Email",
pattern: "{area:exists}/{controller=Email}/{action}/{id?}");
endpoints.MapControllerRoute(
name: "default",
pattern: "{area=Home}/{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
I've tried looking for resources online but I'm at a loss with moving forwards.
The problem is with the action link here. Since you did not mention Area, the default route of Home was selected.
The Actionlink format should be as below:
#Html.ActionLink("Link Text", "ActionName", "ControllerName", new { Area = "AreaName" }, new{})
In you case it should be :
#Html.ActionLink("Roadmap", "RoadMap", "Common", new {Area = "Common"}, new{})
Official Microsoft Documentation :https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.viewfeatures.htmlhelper.actionlink?view=aspnetcore-6.0

ASP.NET core - Activate a route handler only if there is no controller

I have a generic library that manages REST API call and map them to specific files.
For do that, I wrote a Route Handler that matches the url {directory}/{filename}
The library itself works good.
Now I'd like to check if there is any controller for manage the same file.
For example, suppose we write a controller called MyDirectoryController with a GET method called MyFile.
I'd like that the route handler will process the route MyDirectory/anotherfile1, but calls the controller when the path is MyDirectory/MyFile since there is an existing controller.
How can I do that?
I am using .NET core 3.1 and this is the implementation of the route middleware:
public class RestRouteMiddleware
{
public async Task InvokeAsync(HttpContext context)
{
if (context == null) throw new ArgumentNullException(nameof(context));
// I try to check for controller, but it doesn't work
var controllerActionDescriptor = context.GetEndpoint()?.Metadata?.GetMetadata<ControllerActionDescriptor>();
if (controllerActionDescriptor != null &&
!string.IsNullOrEmpty(controllerActionDescriptor.ControllerName) &&
!string.IsNullOrEmpty(controllerActionDescriptor.ActionName)) return;
// Here I manage the request (this code works, but I want to execute
// it only if there is no controller)
...
}
}
According to your description, I suggest you could consider using endpoints.MapFallbackToController to achieve your requirement.
If the url doesn't match other route, it will match this fallbacktocontroller method.
Then you could add some logic inside this controller.
More details, you could refer to below codes:
I create a Fallback controller and its view.
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=home}/{action=index}/{id?}");
endpoints.MapFallbackToController("Index", "Fallback");
});
}
Result:

asp.net core 2.1 custom default route per user

I'vew got an company internal website containing different areas implemented with asp.net core's area-logic.
I'd like to redirect the users to a homepage of their choice.
For Example:
User A: contonso.com/ showing index of area invoices
User B: contonso.com/ showing index of area customers
Possible workaround: Use a generic home controller that redirects the user to the appropriate area but i would like to know if there is a more generic solution using the build-in routing capabilities.
At the moment, i would stores those information in a database but actually i don't care how to configure, as long as I'm able to do the routing dynamically.
The docs and google doesn't say anything about this case.
Is there any way to get arround a custom middleware? Some buildin support, or an existing nuget-package?
You could try Middleware to redirect the requests based on your logic.
Here is a demo code for MVC Controller:
app.Use(async (context, next) =>
{
if (context.Request.Path == "/" && context.User.Identity.Name == "test#outlook.com")
{
context.Response.Redirect("Home/About", true);
}
else if (context.Request.Path == "/" && context.User.Identity.Name == "test1#outlook.com")
{
context.Response.Redirect("Home/Contact", true);
}
await next();
});
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
Note, change the redirect URL and MVC Route based on your Area
U can use action like this:
public IActionResult MyIndex()
{
string action = // get action for user
return RedirectToAction(action, "Home")
}
along with tag helper:
<a asp-controller="Home" asp-action="MyIndex">Go somewhere</a>

How do I configure routing for MVC and SignalR in an ASP.NET Core project?

I'm trying to build a web app with ASP.NET Core 2.1.0-preview1 and ASP.NET Core SignalR 1.0.0-alpha1 with an Angular4 client. So far I've been able to muddle through and can actually open a SignalR web socket connection from within the client. That came at a price, though, here's an excerpt of my Startup.cs:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
/*routes.MapSpaFallbackRoute(
name: "spa-fallback",
defaults: new { controller = "Home", action = "Index" });*/
});
app.UseWebSockets();
app.UseSignalR(routes =>
{
routes.MapHub<Feed>("feed");
});
As you can see, I had to disable the "spa-fallback" route, if I didn't do that SignalR would receive plain HTML instead of JSON. The drawback of that, of course, is that I have to enter the exact URL (localhost:12345/home/index, for example) now, which sucks.
So my question is, how can I make MVC routing and SignalR routing live side by side?
You need to put UseSignalR before UseMvc otherwise the fallback route will be registered before routes added by UseSignalR.

How to have routes aliases?

I look for create a routing system using aliases with ASP.NET Core.
In my database, i have all my routes with the corresponding aliases, when an user request the server my app look for the route corresponding with the alias.
Now, I want to use the recovered route to access the right controller and the right action.
An example will be more explicit than a long speech (what I want to do is in brackets):
The user connects to myapp.com/hello/i/am/an/alias -> The app finds the corresponding route that is /MyController/Index ( -> The app uses MyController to send the Index view to the user )
If someone knows how to do, i take :D thanks
Edit: Actually, the better will be to edit the HttpContext, but I don't think it is possible
Ok, i found the answer !!
It is possible to edit the path in the context like that:
context.Request.Path = new PathString(newPath);
so i used a MapWhen that always return true and edits the context.Request.Path with the database's response and the mapHandler just call app.UseMvc:
private void HandleMap(IApplicationBuilder app)
{
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
app.MapWhen(context => {
string newPath = findNewPath();
context.Request.Path = new PathString(newPath);
return true;
}, HandleMap);
I think you'll want to run something like this in the Configure method of Startup.cs
app.UseMvc(routes =>
{
routes.MapRoute(
name: "path1",
template: "hello/i/am/an/alias",
defaults: {controller="MyController", action="Index"});
routes.MapRoute(
name: "path2",
template: "i/am/another/alias",
defaults: {controller="MyOtherController", action="Index"});
// etc.
});