Asp.net Mvc Route By Only Slug
本文关键字:Only Slug By Route net Mvc Asp | 更新日期: 2023-09-27 18:05:33
我正在使用ASP。NET MVC 4和c#。我用的是区域命名为Admin
这是我的路由配置;
public static class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(name: "PageBySlug",
url: "{slug}",
defaults: new {controller = "Home", action = "RenderPage"},
constraints: new {slug = ".+"});
routes.MapRoute(name: "Default",
url: "{controller}/{action}/{id}",
defaults: new {controller = "Home", action = "Index", id = UrlParameter.Optional},
namespaces: new[] { "Web.Frontend.Controllers.Controllers" });
}
}
我生成的前端页面链接像;"产品/苹果iphone"所以我想这样称呼它们。
但错误是:代码无法获得控制器/动作方法。我使用前端页面链接;
@Html.ActionLink(linkItem.Title, "RenderPage", routeValues: new {controller = "Home", slug = linkItem.PageSlug})
@Html.RouteLink(linkItem.Title, routeName: "PageBySlug", routeValues: new { controller = "Home", action = "RenderPage", slug = linkItem.PageSlug })
<a href="@Url.Action("RenderPage", "Home", new {slug = linkItem.PageSlug})">@linkItem.Title</a>
<a href="@Url.RouteUrl("PageBySlug", new { controller = "Home", action = "RenderPage", slug = linkItem.PageSlug})">@linkItem.Title</a>
它们呈现的url链接是;http://localhost:1231/products/apple-iphone这就是我想要的。但是当我点击任何链接,asp.net mvc给我这个错误:
'/'应用程序出现服务器错误。
无法找到资源。
描述:HTTP 404。您正在查找的资源(或其依赖项之一)可能已被删除、名称已更改或暂时不可用。请查看以下网址,并确保拼写正确。
请求的URL:/products/apple-iphone
版本信息:Microsoft .NET Framework Version:4.0.30319;ASP。净版:4.6.1069.1
这是我的控制器;
namespace Web.Frontend.Controllers
{
public class HomeController : BaseFrontendController
{
public ActionResult Index()
{
return View();
}
public ActionResult RenderPage(string slug)
{
return View();
}
}
}
那么我如何捕获每个链接请求像这个组合的段塞,并把我的编码视图?
问题是,当您请求products/iphone
时,路由引擎不知道您指的是slug "products/iphone"还是控制器"products"和动作方法"iphone"。
你可以编写一个自定义路由约束来处理这个问题。此约束将检查url的slug部分是否为有效的控制器,如果是,将执行控制器操作。
public class SlugConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName,
RouteValueDictionary values, RouteDirection routeDirection)
{
var asm = Assembly.GetExecutingAssembly();
//Get all the controller names
var controllerTypes = (from t in asm.GetExportedTypes()
where typeof(IController).IsAssignableFrom(t)
select t.Name.Replace("Controller", ""));
var slug = values["slug"];
if (slug != null)
{
if (controllerTypes.Any(x => x.Equals(slug.ToString(),
StringComparison.OrdinalIgnoreCase)))
{
return false;
}
else
{
var c = slug.ToString().Split('/');
if (c.Any())
{
var firstPart = c[0];
if (controllerTypes.Any(x => x.Equals(firstPart,
StringComparison.OrdinalIgnoreCase)))
{
return false;
}
}
}
return true;
}
return false;
}
}
现在,当你为slug注册自定义路由定义时,使用这个路由约束。确保在路由模式中使用{*slug}
。*
表示它是任何东西(例如:"a/b/c")(url段的可变数量-更像一个捕获全部)
routes.MapRoute(name: "PageBySlug",
url: "{*slug}",
defaults: new { controller = "Home", action = "RenderPage" },
constraints: new { slug = new SlugConstraint() }
, namespaces: new string[] { "Web.Frontend.Controllers.Controllers" });
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
, new string[] { "Web.Frontend.Controllers.Controllers" });
您只能提供这种类型的链接
<a href="@Url.RouteUrl("PageBySlug", new {slug = linkItem.PageSlug})">@linkItem.Title</a>
Because Routetable使用你提供的route name找到你的路由。所以控制器名和动作名就不需要了