Routing in ASP.NET Core - asp.net

I have two controller based on user type in my ASP.NET Core project. One is AdminController for admin and one is UserController for users. And there is also HomeController for signin and contact page. I am using following map route configuration for both admin and user controllers.
config.MapRoute(
name: "UserRoute",
template: "{controller}/{username}/{action}",
defaults: new { controller = "User|Admin", action = "Dashboard" }
);
By using above route config I am getting following types of Urls
/User/user1
/Admin/user2
I don't want the Admin and User part in URL instead I want
/user1
/user2
How to remove User and Admin part from the URL? If I remove controller from {controller}/{username}/{action} and specify only controller in defaults then it only works for one controller.

You can't have the same URL template with 2 default controllers, because mvc will not understand which controller to use.
You can either have 2 routes and each one with /Admin and /User, just like this:
config.MapRoute(
name: "UserRoute",
template: "User/{username}/{action}",
defaults: new { controller = "User", action = "Dashboard" }
);
config.MapRoute(
name: "AdminRoute",
template: "Admin/{username}/{action}",
defaults: new { controller = "Admin", action = "Dashboard" }
);
And from the Home controller, you can check the user role and redirect him to the correct route.
Another approach, would be only one route as you need
config.MapRoute(
name: "UserRoute",
template: "{username}/{action}",
defaults: new { controller = "User", action = "Dashboard" }
);
But in this version, you will have only one controller and you can enable or disable actions according to the user role

Related

Trying to route parameters to catch all index action on home controller

I am trying to capture parameters into the default home mvc controller which till now I didn't need to do as angular is taking care of all the views/routing.
The reason for this is because I was using angular to set metadata for the SEO. That doesn't work as angular is purely client side. The SEO has to come from the server.
My home controller route is simply this which is a catch all right now, so it needs to stay a catch all but also receive any extra parameters
routes.MapRoute(
name: "Default",
url: "{*.}",
defaults: new { controller = "Home", action = "Index" }
);
So I can capture something in the url like this ie 'product'
public ActionResult Index(string product = "")
{
var meta = new MetaData
{
Title = "Test",
Description = "Desc1",
Keywords = ""
};
return View("Index",meta);
}
I can't use something like
url: "{controller}/{action}/{id}",
Because then it will expect views/controllers for my other pages which are taken care of by angular.
So I need a default route that will use the home controller whenever the url is like this
mywebsitename.com/showmen
I tried
url: "*./{product}",
but that is invalid. I also changed the route to
routes.MapRoute(
name: "Default",
url: "{*.}",
defaults: new { controller = "Home", action = "Index" , product = UrlParameter.Optional}
);
But that doesn't work.
I removed the catch all route and just used a default one like this for the home page
routes.MapRoute(
name: "HomePage",
url: "",
defaults: new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional
}
);
Without the catch all I had to add quite a few routes for the other pages like this
routes.MapRoute(
name: "LandingPage",
url: "landingpage/{product}",
defaults: new
{
controller = "Home",
action = "Landing",
product = UrlParameter.Optional
}
);
So now i can capture the product and send the metadata to _Layout using the same index view. Meanwhile the angular route still does what it did before.
Anything that receives a quoteref/password all use a generic route that passes to the home controller index action to update the same model on _Layout.

How to catch all routes but ignore some URLs?

I'm starting to upgrade my old WebForms CMS which uses a catch all handler.
In .NET Core 2 I have created a route like:
routes => {
routes.MapRoute(
name: "NodeHandler",
template: "{*url}",
defaults: new { controller = "Node", action = "Index" );
}
Which by default catch all. How do I get the route to ignore certain directories?
Attribute-based routing. In your controllers use the [NonAction] attribute so that no route will be created for an action.
The default route (template) is {controller}/{action}/{id} but you can have non-action methods using this technique.
Controllers and Actions

Authorize attribute on a controller inside an area

I have an Area with a few controllers inside it, decorated with the [Authorize] attribute. I also have a few controllers outside the area. To default to the controller inside the area, I have updated my routes, to look like:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new string[] { "e_Forms.Controllers" }
).DataTokens.Add("area","RefundRequest");
Now, the redirection works, when i try to access with http://localhost:58000/.
But, the problem here is, the authorize attribute does not redirect to the login page. The redirection happens only when I try to access using http://localhost:58000/RefundRequest/Request. Also, the breakpoints are not hit in the controller(but are hit inside the view) when I try to access using the former.
Please suggest what is happening here, and a workaround to this.
EDIT 1:
When I changed my route definition to:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { area="RefundRequest", controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new string[] { "e_Forms.Areas.RefundRequest.Controllers" }
).DataTokens.Add("area","RefundRequest");
the authorize attribute works fine. but then it does not allow me access to the Home controller outside of areas which is not marked with [Authorize].

Asp.Net: Removing the action name from the URL

I am trying to create a routing rule that allows me to use
http://localhost:*****/Profile/2
instead of
http://localhost:*****/Profile/Show/2
to access a page. I currently have a routing rule that successfully removes index when accessing a page. How do I apply the same concept to this?
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
I have a couple of questions to clarify what you are trying to do. Because there could be some unintended consequences to creating a custom route.
1) Do you only want this route to apply to the Profile controller?
Try adding this route before the default route..
routes.MapRoute(
name: "Profile",
url: "Profile/{id}",
defaults: new { controller = "Profile", action = "Show" }
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
This new route completely gets rid of the Index and other actions in the Profile controller. The route also only applies to the Profile controller, so your other controllers will still work fine.
You can add a regular expression to the "id" definition so that this route only gets used if the id is a number as follows. This would allow you to use other actions in the Profile controller again as well.
routes.MapRoute(
name: "Profile",
url: "Profile/{id}",
defaults: new { controller = "Profile", action = "Show" }
defaults: new { id= #"\d+" }
);
Also, it would be a good idea to test various urls to see which route would be used for each of the urls. Go to NuGet and add the "routedebugger"
package. You can get information on how to use it at http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx/

ASP.NET MVC routing: URL is falling into the wrong route

I'm working into a really common mvc Project and I have three diferents routes:
Route for display products by id
routes.MapRoute(
"get-by-id",
"{controller}/{id}",
new { action = "GetById" },
new { id = #"\d+" }
);
Route for display products by category
routes.MapRoute(
"get-by-category",
"{controller}/{category}",
new { action = "GetByCategory" },
new { category = #"\w+" }
);
Default route
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Conslusion: I want the /products/create request falls into the default route (because I want "create" to be rendered as an action) and not into the get-by-category route (because it take "create" as a string).
Use Route Debuger it will help you debug your routes to figure out which routes are being called when. One of the tools I always nuget when working on asp.net mvc.
BTW - looking at your routes there is no route there that maps to Product/Create. In which case it is just going to take you to the default route. You need to have a route specified which is going to map to the Products controller and if you want to have an action of Create it will need to have "Products/Create" with its action pointing to Get-by-id action
routes.MapRoute(
"get-by-id",
"{controller}/Create/{id}",
new { action = "GetById" },
new { id = #"\d+" }
);

Resources