如何拦截Url以动态更改路由

本文关键字:路由 动态 何拦截 Url | 更新日期: 2023-09-27 18:27:56

我想做一些类似的事情:

对于控制器为CategoryController 的类别

www.mysite.com/some-category
www.mysite.com/some-category/sub-category
www.mysite.com/some-category/sub-category/another //This could go on ..

问题是:www.mysite.com/some-product需要指向一个ProductController。通常情况下,这会映射到同一个控制器。

那么,我如何拦截路由,以便检查参数是否为Category或Product,并相应地进行路由。

我尽量避免使用www.mysite.com/category/some-categorywww.mysite.com/product/some-product,因为我觉得它在SEO方面会表现得更好。当我可以拦截路由时,我会根据一些规则转发到一个产品/类别,这些规则会为每个等查看slugs。

如何拦截Url以动态更改路由

您可以编写一个自定义路由来实现此目的:

public class CategoriesRoute: Route
{
    public CategoriesRoute()
        : base("{*categories}", new MvcRouteHandler())
    {
    }
    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        var rd = base.GetRouteData(httpContext);
        if (rd == null)
        {
            return null;
        }
        string categories = rd.Values["categories"] as string;
        if (string.IsNullOrEmpty(categories) || !categories.StartsWith("some-", StringComparison.InvariantCultureIgnoreCase))
        {
            // The url doesn't start with some- as per our requirement =>
            // we have no match for this route
            return null;
        }
        string[] parts = categories.Split('/');
        // for each of the parts go hit your categoryService to determine whether
        // this is a category slug or something else and return accordingly
       if (!AreValidCategories(parts)) 
       {
           // The AreValidCategories custom method indicated that the route contained
           // some parts which are not categories => we have no match for this route
           return null;
       }
        // At this stage we know that all the parts of the url are valid categories =>
        // we have a match for this route and we can pass the categories to the action
        rd.Values["controller"] = "Category";
        rd.Values["action"] = "Index";
        rd.Values["categories"] = parts;
        return rd;
    }
}

将像这样注册:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.Add("CategoriesRoute", new CategoriesRoute());
    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}

然后你就可以有相应的控制器:

public class CategoryController: Controller
{
    public ActionResult Index(string[] categories)
    {
        ... The categories action argument will contain a list of the provided categories
            in the url
    }
}