I would like to create a dynamic routing to a URL like following:
http://localhost:51577/Item/AnyActionName/Id
Please note that the controller name is static and doesn't need to be dynamic. On the other hand, I need to have the action name part dynamic so that whatever is written in that part of URL, I would redirect the user to the Index action inside of Item controller.
What I have tried so far is:
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute(
"Items",
"Item/{action}/{id}",
new { controller = "Item", action = "Index", id = UrlParameter.Optional });
}
And when I build my app I get a following error:
The resource cannot be found.
Edit:
Here is my Global.asax file and the routeconfig.cs file:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
And here's the content of the RouteConfig.cs file with the answer that #Nkosi provided:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Items",
url: "Item/{id}/{*slug}",
defaults: new { controller = "Item", action = "Index", slug = UrlParameter.Optional }
);
}
}
What you are referring to in your question is called a slug.
I answered a similar question here for web api
Web api - how to route using slugs?
With the slug at the end the route config would look like this
public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Items",
url: "Item/{id}/{*slug}",
defaults: new { controller = "Item", action = "Index", slug = RouteParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
which could match an example controller action...
public class ItemController : Controller {
public ActionResult Index(int id, string slug = null) {
//...
}
}
the example URL...
"Item/31223512/Any-Item-Name"
would then have the parameters matched as follows...
id = 31223512
slug = "Any-Item-Name"
And because the slug is optional, the above URL will still be matched to
"Item/31223512"
Related
I've a strange behavior of configured route in Route Config in MVC5 app.
So, actually I try to do pretty much easy thing - change default action of a route.
To do that I've changed the defaults of a route, instead of having action = "Index", I've changed it to my required action AddUser (Look at the code below).
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "ManageUser",
url: "{controller}/{action}/{id}",
defaults: new { controller = "ManageUser", action = "AddUser", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
And I've next controller:
[Authorize(Roles ="Admin")]
public class ManageUserController : Controller
{
// GET: ManageUser/AddUser
[HttpGet]
public ActionResult AddUser()
{
return View();
}
}
So, now I expect that whenever user goes by URL: ManageUser/ he'll be redirected to defined default action but it doesn't happen, I just have 404 error. I can fix it simply by adding Index action and then redirect to AddUser, but it doesn't seem right to me. Could somebody help me understand what I've done wrong?
I think, your config should look like this:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"ManageUser",
"ManageUser/{action}/{id}",
new { controller = "ManageUser", action = "AddUser", id = UrlParameter.Optional }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
The first parameter is the name of the route. Second is the URL, which match URLs that start with ManageUser, and allows for other actions in your ManageUser controller. As you can see, it will default to the AddUser action.
And if you want to call AddUser with paramater, you must call it by full url ManageUser/AddUser/1
I want to ask if it's possible to have more than one routing within RouteConfig class. The logic I have is as below, what I want to achieve. I have actionLink("Dashboard", "Account".....) already and want to have a unique one that won't conflict with existing one when page is loaded. Please assist me there is a way.
namespace ContentManagementSystem
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } // I already have this working fine
defaults: new { controller = "Dashbaord", action = "_Index", id = UrlParameter.Optional // I want to have separate, but unique route for this controller for actionResult
);
}
}
}
Yes you can have more routes you can :
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Student",
url: "students/{id}",
defaults: new { controller = "Student", action = "Index"}
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
As shown in the above code, URL pattern for the student route is students/{id}, which specifies that any URL that starts with domainName/students, must be handled by the StudentController.
Notice that we haven't specified {action} in the URL pattern because we want every URL that starts with student should always use Index action of StudentController. We have specified default controller and action to handle any URL request which starts from domainname/students.
You can read more here
Add it to top of default route:
namespace ContentManagementSystem
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute("other_route", "other_route/",
defaults: new { controller = "OtherController", action = "OtherAction" });
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } // I already have this working fine
defaults: new { controller = "Dashbaord", action = "_Index", id = UrlParameter.Optional // I want to have seperate, but unique route for this controller for actionResult
);
}
}
}
This question already has answers here:
Routing in ASP.NET MVC, showing username in URL
(2 answers)
Closed 4 years ago.
I have an Asp.Net MVC project whereby we allow our users to have public profiles.
I would like to improve the url, so that it is more friendly, and shorter.
The existing code is as follows -
public class ProfileController : Controller
{
private readonly IUserProfileService _userProfileService;
public ProfileController(IUserProfileService userProfileService)
{
this._userProfileService = userProfileService;
}
public ActionResult Index(string id)
{
//Get users profile from the database using the id
var viewModel = _userProfileService.Get(id);
return View(viewModel);
}
}
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//Required for the route prefix attributes to work!
routes.MapMvcAttributeRoutes();
routes.MapRoute(
"ProfileUrlIndexActionRemoval",
"Profile/{id}",
new { controller = "Profile", action = "Index" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
The aforementioned code allows the following url to work (based on the default MVC routing) - www.mydomain.com/profile/john-doe
What routing do I need to implement, in order to allow the following url to work instead - www.mydomain.com/john-doe
Thanks.
This is a little tricky as you want the friendly URL in the root of the site while not conflicting with any other routes.
That would mean that if you have any other routes like About or Contact you would need to make sure that are in the route table before the friendly route to avoid route conflicts.
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//Required for the route prefix attributes to work!
routes.MapMvcAttributeRoutes();
routes.MapRoute(
"ProfileUrlIndexActionRemoval",
"Profile/{id}",
new { controller = "Profile", action = "Index" }
);
routes.MapRoute(
name: "Home",
url: "Home/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "About",
url: "About/{action}/{id}",
defaults: new { controller = "About", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Contact",
url: "Contact/{action}/{id}",
defaults: new { controller = "Contact", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
"Default_Frieldly",
"{*id}",
new { controller = "Profile", action = "Index" }
);
}
}
And finally because the default route will capture all unmatched routes, you will need to take not found profiles into account.
public class ProfileController : Controller {
//...code removed for brevity
public ActionResult Index(string id) {
//Get users profile from the database using the id
var viewModel = _userProfileService.Get(id);
if(viewModel == null) {
return NotFound();
}
return View(viewModel);
}
}
By having the profile controller prefix in the original URL it made it unique so as to avoid route conflicts, but in wanting the root friendly URL, while not impossible, you see the hoops needed to jump through in order to get the desired behavior.
This is how I would do it. Register a route that matches any string after the root slash.
Note that this severely limits the routes you can use for the application since not everything matching /{id} may actually be a user ID, which is why applications will typically prefix the route with /profile or /p.
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute(
name: "UserIdRoute",
url: "{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
public ActionResult Index(string id)
{
//Get users profile from the database using the id
var viewModel = _userProfileService.Get(id);
return View();
}
When I try to access to index Page on controller if I use this URL format :
mydomain/taux/index
This works and the Index page is opened. But if I use this url format (I don't add the Index action to URL)
mydomain/taux/
I got "404 not found", but normally it should works and redirect me to index page automatically.
How to fix it please ?
Taux Controller :
// GET: /Taux/
public ActionResult Index()
{
var taux = db.TAUX.Include(t => t.CATEGORIE).Include(t => t.GARANTIE);
return View(taux.ToList());
}
RouteConfig.cs:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Account", action = "Login", id = UrlParameter.Optional }
);
}
}
This is because your default action is set to Login. You need to set it to Index if you want link mydomain/taux/ to redirect to Indext action
If you want to have the redirect just for this specific controller you can use the following route definitions:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Taux",
url: "Taux/{action}/{id}",
defaults: new { controller = "Taux", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Account", action = "Login", id = UrlParameter.Optional }
);
}
my VisitsController:
public ActionResult Index(Visits visits, int? id)
{
....
return View(v);
}
Here is my route config
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index",
id = UrlParameter.Optional }
);
}
Works: http://localhost:49225/Visits
Does not work: http://localhost:49225/Visits/123
What would the custom route be (and force it to be an integer)?
You need to add a new route for that to work.
Currently, this will work:
/Visits/Index/123
I believe you need to add the following:
routes.MapRoute(
name: "VisitsDefault",
url: "Visits/{id}",
defaults: new { controller = "Visits", action = "Index",
id = UrlParameter.Optional }
);
This is assuming you have a modelbinder for Visits already.