基本上我有一个使用ASP.NET MVC构建的CMS后端,现在我正在进入前端站点,需要能够根据输入的路由从我的cms数据库加载页面。
因此,如果用户输入domain.com/students/information,MVC会在页面表中查看是否存在具有与学生/信息匹配的永久链接的页面,如果是,则会重定向到页面控制器,然后从数据库加载页面数据并将其返回到视图以供显示。
到目前为止,我已尝试捕获所有路径,但它仅适用于两个URL段,因此/学生/信息,但不适用于/ students / information / fall。我在网上找不到任何关于如何实现这一点的内容,所以我会在这里问一下,然后才找到并开源ASP.NET MVC cms并剖析代码。
这是我到目前为止的路线配置,但我觉得有更好的方法可以做到这一点。
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" }
);
}
如果有人能指出我如何从数据库加载CMS页面,最多有三个URL段,并且仍然能够加载具有预定义控制器和操作的核心页面。 / p>
答案 0 :(得分:117)
您可以使用约束来决定是否覆盖默认路由逻辑。
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;
}
}
在路线定义中使用它,例如,
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 }
);
现在,如果您在“页面”控制器中有“索引”操作,例如
public ActionResult Index(string permalink)
{
//load the content from db with permalink
//show the content with view
}
修改强>
为避免在Index
控制器中的Page
操作中重新查询cms页面,可以使用HttpContext.Items
字典,例如
中的约束
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;
然后在行动中,
public ActionResult Index(string permalink)
{
var page = HttpContext.Items["cmspage"] as CMSPage;
//show the content with view
}
希望这会有所帮助。
答案 1 :(得分:0)
我使用更简单的方法,不需要任何自定义路由器处理。 只需创建一个处理一些可选参数的单个/全局控制器,然后根据需要处理这些参数即可:
@SpringBootTest
class SomeTest {
@Autowired
lateinit var webApplicationContext: WebApplicationContext
lateinit var mockMvc: MockMvc
@BeforeEach
fun beforeEach() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build()
}
// Tests go here!
}
domain.com/test1/test2/test3上的示例输出
//Route all traffic through this controller with the base URL being the domain
[Route("")]
[ApiController]
public class ValuesController : ControllerBase
{
//GET api/values
[HttpGet("{a1?}/{a2?}/{a3?}/{a4?}/{a5?}")]
public ActionResult<IEnumerable<string>> Get(string a1 = "", string a2 = "", string a3 = "", string a4 = "", string a5 = "")
{
//Custom logic processing each of the route values
return new string[] { a1, a2, a3, a4, a5 };
}
}