Dynamic routes from the database for ASP.NET MVC CMS

Basically I have a CMS server that I created using ASP.NET MVC, and now I go to the frontend site and should be able to load pages from my cms database based on the entered route.

Thus, if the user enters domain.com/students/information, MVC will look in the page table to see if there is a page that has a permalink that matches students / information, if that is redirected to the page controller, and then load the page data from the database and return it to the view for display.

So far I have been trying to catch the entire route, but it only works for two segments of the URL, so / students / information, but not / students / information / fall. I can’t find anything on the Internet about how to do this, so although I would ask here before I find and compile open source ASP.NET MVC and analyze the code.

Here is the route configuration that I have so far, but I believe there is a better way to do this.

public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); // Default route to handle core pages routes.MapRoute(null,"{controller}/{action}/{id}", new { action = "Index", id = UrlParameter.Optional }, new { controller = "Index" } ); // CMS route to handle routing to the PageController to check the database for the route. var db = new MvcCMS.Models.MvcCMSContext(); //var page = db.CMSPages.Where(p => p.Permalink == ) routes.MapRoute( null, "{*.}", new { controller = "Page", action = "Index" } ); } 

If anyone can point me in the right direction, how will I load CMS pages from the database, up to three URL segments and still be able to load the main pages that have a predefined controller and action.

+64
c # asp.net-mvc-4 routes
Apr 15 '13 at 23:42
source share
2 answers

You can use a constraint to decide whether to override the default routing logic.

 public class CmsUrlConstraint : IRouteConstraint { public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) { var db = new MvcCMS.Models.MvcCMSContext(); if (values[parameterName] != null) { var permalink = values[parameterName].ToString(); return db.CMSPages.Any(p => p.Permalink == permalink); } return false; } } 

use it in your route definition e.g.

 routes.MapRoute( name: "CmsRoute", url: "{*permalink}", defaults: new {controller = "Page", action = "Index"}, constraints: new { permalink = new CmsUrlConstraint() } ); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); 

Now, if you have an “Index” action in the “Page” controller, for example,

 public ActionResult Index(string permalink) { //load the content from db with permalink //show the content with view } 
  • all URLs will be caught on the first route and will be checked by restriction.
  • If the permalink exists in db, then the URL will be processed by the pointer in the page controller.
  • If it doesn’t hold back the restriction, and the url will return to the default route (I don’t know if you have any other controllers in the project and how you decide your 404 logic).

EDIT

To avoid querying the cms page in Index in the Page controller, you can use the HttpContext.Items dictionary, for example

in limiting

 var db = new MvcCMS.Models.MvcCMSContext(); if (values[parameterName] != null) { var permalink = values[parameterName].ToString(); var page = db.CMSPages.Where(p => p.Permalink == permalink).FirstOrDefault(); if(page != null) { HttpContext.Items["cmspage"] = page; return true; } return false; } return false; 

then in action

 public ActionResult Index(string permalink) { var page = HttpContext.Items["cmspage"] as CMSPage; //show the content with view } 

hope this helps.

+118
Apr 16 '13 at 7:13
source share

I use a simpler approach that does not require any special router processing. Just create one / global controller that handles a few optional parameters, then process these parameters the way you like:

 //Route all traffic through this controller with the base URL being the domain [Route("")] public class MyController : Controller { //Define up to 5 optional patrameters [HttpGet("{a1?}/{a2?}/{a3?}/{a4?}/{a5?}")] public async Task<JsonResult> APIGet(string a1 = "", string a2 = "", string a3 = "", string a4 = "", string a5 = "") { //Custom logic processing each of the route variables return Json(new string[] { a1, a2, a3, a4, a5 }); } } 

Example output on domain.com/test1/test2

 ["test1","test2","","",""] 
0
Jul 03 '19 at 19:59
source share



All Articles