Dynamic url routes ASP MVC
Im trying to make a very simple application that lets my client create their own pages. The h开发者_开发技巧ard part is to let them create thir own URL.
Client need to fill in:
- Page name (ex. About us).
- Page description (ex. We are a big company).
- Page URL relative (ex. /About)
When client enter this information and save, it should be saved in the database.
I can easily create a controller named "Page" which takes a value "ID" and when a user enters "www.someurl.com/Page/1" the newly created page pops up.
But what I really want is for the user to write "www.someurl.com/About" and then the page pops up.
How can this be done with some kind of dynamic rewrite/route code using ASP MVC.
My idea would be to create a field in your 'Page' table called 'Slug.' When your user creates a new page they would have to fill out the 'Slug' field and enter what they would like to see in the url (ex: page wanted - "About", slug - "about" | page wanted - "See Our Sponsors", slug - "see-our-sponsors" | etc). You can automate this process with a little bit of javascript if you want.
Create a route like so:
routes.MapRoute(
null,
{slug},
new { controller = "Page", action = "ChoosePage" });
Create an action method like so:
[AcceptVerbs(HttpVerbs.Get)]
public ViewResult ChoosePage(string slug)
{
//Logic to display page
}
Basically it would work like your idea of putting the page id in the url but it would be much cleaner and it would use 'slug' to do the database lookup instead of the page id.
As the number of questions about routing on this site indicates, handling multiple, potentially overlapping routes correctly is tricky even for programmers. Putting this kind of broad-reaching functionality in the hands of end-users is terrifying.
To answer your question, it's fairly simple to read the "custom" routes from the database at application startup and map them as usual. You don't typically do this during application execution, as the route list will be shared amongst multiple threads. If you dig into the routing source code, you'll probably find a way to protect a "rebuild" of the routing table if you determine that you must do it during execution.
However, I'd strongly suggest that you go with your "Site" controller idea instead. Consider the following: Routing is used both for parsing incoming URIs and for generating URIs. If there is even one case in your application where you use ActionLink
instead of RouteLink
, then consider that a route added by a user could potentially break your entire site. Meaning that the user would be unable to fix their mistake, even if they realized that they had caused it.
Best idea I have in mind would be to use the "last case scenario" idea.
Basically you have this scenario.
1- normal routing (eg: controller/action/id route).
2- any special route/area you may set (eg: admin)
3- write a catchall route. This route will search in db for a page named by the route. If this route does not exists, it will throw a 404 page not found error.
This is how the final code looks like, thanks to all of you who helped!
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Home",
"",
new { controller = "Home", action = "Index" }
);
routes.MapRoute(
"Account",
"Account/{action}",
new { controller = "Account", Action = "Index" }
);
routes.MapRoute(
"Page",
"{*slug}",
new { controller = "Page", action = "ChoosePage" }
);
}
This can be done by following way:
1.Insert new route for that page in the RouteTable
RouteTable.Routes.Insert(1,new Route("Test", new RouteValueDictionary(new { controller = "Page", action = "ChoosePage" ,pagename="Test" }), new MvcRouteHandler()));
public ActionResult ChoosePage(string pagename)
{
return View(pagename);
}
This will solve routes for the newly created page at runtime but this needs to be saved in the database.
- Write codes to retrieve all Routes from database and write in Global.asax.cs file Application_Start()
精彩评论