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) {
- 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;
hope this helps.
shakib Apr 16 '13 at 7:13 2013-04-16 07:13
source share