How do I generate friendly URLs within the ASP.NET MVC Framework? For example, we've got a URL that looks like this:
http://site/catalogue/BrowseByStyleLevel/1
The 1 is Id of the study level (Higher in this case) to browse, but I'l like to reformat the URL in the same way StackOverflow does it.
For example, these two URLs will take you to the same place:
https://stackoverflow.com/questions/119323/nested-for-loops-in-different-languages
https://stackoverflow.com/questions/119323/
EDIT: The friendly part of the url is referred to as a slug.
There are two steps to solve this problem. First, create a new route or change the default route to accept an additional parameter:
routes.MapRoute( "Default", // Route name
"{controller}/{action}/{id}/{ignoreThisBit}",
new { controller = "Home",
action = "Index",
id = "",
ignoreThisBit = ""} // Parameter defaults )
Now you can type whatever you want to at the end of your URI and the application will ignore it.
When you render the links, you need to add the "friendly" text:
<%= Html.ActionLink("Link text", "ActionName", "ControllerName",
new { id = 1234, ignoreThisBit="friendly-text-here" });
This is how I have implemented the slug URL on my application.
Note: The default Maproute should not be changed and also the routes are processed in the order in which they're added to the route list.
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home",
action = "Index",
id = UrlParameter.Optional
} // Parameter defaults
);
routes.MapRoute("Place", "{controller}/{action}/{id}/{slug}", new { controller = "Place", action = "Details", id = UrlParameter.Optional,slug="" });
you have a route on the global.asax
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = ""}
// Parameter defaults )
you can define your own route like :
controller is the cs class inside the the controllers folder.
you can define your id - with the name you choose.
the system will pass the value to your actionResult method.
you can read more about this step here : http://www.asp.net/learn/mvc/tutorial-05-cs.aspx
Related
Given this URL's
http://localhost:51095/Person // This is equivalent to this one Person/Index
http://localhost:51095/Person/Allan
I setup a route config for it as follows :
routes.MapRoute(
"Person",
"Person/{personName}",
new { controller = "Person", action = "Person", personName = UrlParameter.Optional }
)
;
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
First URL should follow the Default route and the second should follow the Person route.
This is not working because the first config seems to catch all these URL's
The first thing I'd do is remove personName = UrlParameter.Optional in the first Route. This would allow only urls that provide a personName value to access this Route. If no value is provided, it should fall through to the default Route.
But you'd want to think about the future with this strategy: if you implement new actions on that Person controller, you'd need to add a new Route for each of them. If you had a new 'Edit' action for example:
routes.MapRoute(
"Person_Edit",
"Person/Edit/{personName}",
new { controller = "Person", action = "Edit" }
)
You'd want to add these new Routes before the first one though - ordering/precedence of Routes is important.
If I have the following MapRoute:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
I can have an url like:
blabla.com/Home/Index/123
But what kind of MapRoute do I need to create to be able to do this:
blabla.com/Home/123 or blabla.com/Home/DEADBEEF?
I imagine it involves something along the lines of
"{controller}/{id}/{action}"
Action and id are reversed, and maybe there should be a default action. But how will the MapRoute know which controller should be treated like this?
You probably need something along these lines.
routes.MapRoute(
name: "DefaultRoute",
url: "Home/{action}",
defaults: new { controller = "Home", action = "Index" },
constraints: new { action = "[A-Za-z]*" }
);
or without an action
routes.MapRoute(
name: "DefaultRoute",
url: "Home/{id}",
defaults: new { controller = "Home", action = "Index", id = "" },
constraints: new { id = "[A-Za-z]*" }
);
You will need to make sure that the route name is different than any other routes you have setup and pay attention to the ordering of the routes as other routes that are similar can override each other. In this case make sure you would probably want this before the default route but be aware that it will override it.
As for the not having controller or even the action you can set defaults and do not need them within the route.
As for constraints you can simply add the constraints parameter to the route to set a regular expression for a certain attribute as shown above.
EDIT:
Here are some useful links for more info on routing if you need it.
http://www.dotnet-tricks.com/Tutorial/mvc/HXHK010113-Routing-in-Asp.Net-MVC-with-example.html
http://weblogs.asp.net/scottgu/archive/2007/12/03/asp-net-mvc-framework-part-2-url-routing.aspx
Advanced ASP Routing tutorials and examples
You can add a route like this:
routes.MapRoute(
"CustomRoute",
"Home/{id}",
new { controller = "Home", action = "Index", id = "" });
Make sure you place it above the default route. However this route will block all the other actions in HomeController. Since we don't have a constraint on id parameter, the framework can't possibly know if you are referring to an action or an id in your URL. Since this route comes first, it will map it to id parameter.
I am trying to write a rule to map a URL but so for I did not get the results I want. I have this rule so far:
routes.MapRoute(
"Search", // Route name
"{controller}/{action}/{product}/{page}", // URL with parameters
new { controller = "Home", action = "Search", product = UrlParameter.Optional, page = UrlParameter.Optional } // Parameter defaults
);
using this I can achieve this result so far:
localhost:8493/home/search/myproduct
localhost:8493/home/search/myproduct/2
but i want to do something like this:
localhost:8493/myproduct
so this will route to home/search/myproduct
I have tried the following but it didn't work:
routes.MapRoute(
"DirectSearch", // Route name
"{product}/{page}", // URL with parameters
new { controller = "Home", action = "Search", } // Parameter defaults
);
Is there a way to do this?
Add:
So Here i added the specific route to map to another action but it doesn't work:
routes.MapRoute(
"Tuna",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Tuna", id = UrlParameter.Optional }
);
You're close I think. This should work;
routes.MapRoute(
"Search", // Route name
"{product}/{page}", // URL with parameters
new { controller = "Home", action = "Search", product = UrlParameter.Optional, page = UrlParameter.Optional } // Parameter defaults
);
Just remember that the framework will read the route data from top to bottom and use the first one it finds that matches. So make sure the more specific routes are listed before the more general ones
Edit
Here's a link to a discussion on custom routing
I've got the following routes:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(null,"Conference/{shortName}/Submission/{submission}/{action}", new { controller = "Conference", action = "Show" });
routes.MapRoute(null,"Conference/{shortName}/{action}",new { controller = "Conference", action = "Index" });
routes.MapRoute("Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
The following (hopefully obvious) links which are all working:
/Conference/testconf
/Conference/testconf/ShowSubmissions
/Conference/testconf/Submission/firstSub
/Conference/testconf/Submission/firstSub/EditSubmission
When I'm now in Submission/firstSub and create a ActionLink like this
#Html.ActionLink("Show Submissions", "ShowSubmissions", "Conference", new { shortName = Model.confereceShortName },null)
it creates the following Link
/Conference/testconf/Submission/firstSub/ShowSubmissions
How can i let the actionlink forget about Submission/firstSub without hardcoding it there?
Where do you have a placeholder for {controller}?
The default route should look like the following sample.
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{*id}", // URL with parameters
new {controller = "Home", action = "Index", id = UrlParameter.Optional} // Parameter defaults
);
Also try to remove the /Submission/ part in your first route.
Links for posts on custom route creation and ordering:
1) Creating Custom Routes (C#)
2) Custom routing for ASP .NET MVC
3) official source from asp.net mvc
Sometimes searching for 30min isn't enough, you gotta search 2h...
ASP.NET MVC 2 RC2 Routing - How to clear low-level values when using ActionLink to refer to a higher level?
Routlink or delete the values in the constraints.
For me Routelink does the job.
Although Thanks
ElYusubov & Aleksey
I need to access a parameter without name.
Ex: I have a controller test, I want to get "data" in mysite.com/test/data. Without calling the action data.
I know how to do that passing it though Index action.
public ActionResult Index(string id)
That way I'd only need to type mysite.com/test/Index/data to get "data", but I don't want to have to type Index.
Does anyone know how to do it?
EDIT:
Thanks a lot to #andyc!
AndyC I used what you said and created a test. It worked =D
Now I can type mysite.com/something and if something is not an controller it redirects to my profile page.
This is what is working for me
routes.MapRoute(
"Profile",
"{id}",
new { Controller = "Profile", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
Setup a custom route
In your global.asax file, put (Inside the RegisterRoutes method):
routes.MapRoute(
"MyShortRoute",
"view/{id}",
new { Controller = "test", action = "Index" }
);
The first parameter is a name, the second is the URL format and the last parameter is the default values (in this case if you leave id empty it'll default to id 0.
Notice that I don't use test/{id} as this would also match test/Edit, where edit is an action that you do not want passed as a parameter (I can't think of another way to avoid this, especially if you're using strings instead of ints for your parameters).
Remember to order your routes appropriately in your global.asax file. Put more specific routes before less specific routes. When the system is searching for a route to take, it does not attempt to find the most specific match but instead it starts from the top, and uses the first match it finds.
Therefore, this is bad:
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "test", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
"Specific",
"test/{id}",
new { controller = "test", action = "Index", id = 0 }
);
In this example, if you browse to test/somevalue it will match the FIRST entry, which is not what you want, giving you the testcontroller and the somevalue action.
(As your adding a more specific route, you will want it near the top, and definitely before your default).