Asp.net mvc 使用路由操作url

Asp.net mvc 使用路由操作url,asp.net-mvc,asp.net-routing,Asp.net Mvc,Asp.net Routing,在我的网站中,我定义了以下路线: routes.MapRoute( name: "Specific Product", url: "product/{id}", defaults: new { controller = "", action = "Index", id = UrlParameter.Optional } ); 这样,我希望客户能够添加产品的ID并转到产品页面 SEO顾问说,如果我们可以在URL上添加产品描述,比如产品名称或其他内容,那会更好。因此,URL应该类

在我的网站中,我定义了以下路线:

routes.MapRoute(
   name: "Specific Product",
   url: "product/{id}",
   defaults: new { controller = "", action = "Index", id = UrlParameter.Optional }
);
这样,我希望客户能够添加产品的ID并转到产品页面

SEO顾问说,如果我们可以在URL上添加产品描述,比如产品名称或其他内容,那会更好。因此,URL应该类似于:

/产品/我的酷产品名称/123

/product/my-cool-product-name-123

当然,描述存储在数据库中,我不能用url重写来实现这一点(或者我可以吗?)

我是否应该在我的控制器上添加重定向(这似乎可以完成任务,但感觉不太对劲)

在我检查过的一些网站上,他们的回复是永久移动的
301
。这真的是最好的方法吗

更新

根据斯蒂芬·穆克(Stephen Muecke)的评论,我查看了正在发生的事情

建议的url是我自己的,我打开控制台查看任何重定向。以下是一个屏幕截图:


首先,非常感谢@StephenMuecke为Slug提供了提示,以及他建议的url

我想发布我的方法,这是一个混合的网址和其他几篇文章

我的目标是让用户输入一个url,如:

/产品类别∕123

当页面加载时,在地址栏中显示如下内容:

/product/my-awsome-product-name-123

我检查了几个具有这种行为的网站,似乎在我检查的所有网站中都使用了
301永久移动
响应。即使如此,如我的问题中所示,使用
301
添加问题的标题。我认为会有一种不同的方法,不需要第二次往返

因此,我在本例中使用的总体解决方案是:

  • 我创建了一个
    SlugRouteHandler
    类,它看起来像:

    public class SlugRouteHandler : MvcRouteHandler
    {
        protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            var url = requestContext.HttpContext.Request.Path.TrimStart('/');
    
            if (!string.IsNullOrEmpty(url))
            {
                var slug = (string)requestContext.RouteData.Values["slug"];
                int id;
    
                //i care to transform only the urls that have a plain product id. If anything else is in the url i do not mind, it looks ok....
                if (Int32.TryParse(slug, out id))
                {
                    //get the product from the db to get the description
                    var product = dc.Products.Where(x => x.ID == id).FirstOrDefault();
                    //if the product exists then proceed with the transformation. 
                    //if it does not exist then we could addd proper handling for 404 response here.
                    if (product != null)
                    {
                        //get the description of the product
                        //SEOFriendly is an extension i have to remove special characters, replace spaces with dashes, turn capital case to lower and a whole bunch of transformations the SEO audit has requested
                        var description = String.Concat(product.name, "-", id).SEOFriendly(); 
                        //transform the url
                        var newUrl = String.Concat("/product/",description);
                        return new RedirectHandler(newUrl);
                    }
                }
    
            }
    
            return base.GetHttpHandler(requestContext);
        }
    
    }
    
  • 从上面我还需要创建一个
    RedirectHandler
    类来处理重定向。这实际上是从

  • 有了这两个类,我可以将产品ID转换为SEO友好的URL

    为了使用这些,我需要修改我的路由以使用
    SlugRouteHandler
    类,这将导致:

  • 从路由调用
    SlugRouteHandler
    class

    routes.MapRoute(
       name: "Specific Product",
       url: "product/{slug}",
       defaults: new { controller = "Product", action = "Index" }
    ).RouteHandler = new SlugRouteHandler();
    
  • 下面是他评论中提到的@StephenMuecke的用法

    我们需要找到一种方法来映射新的搜索引擎优化友好的网址到我们的实际控制人。我的控制器接受整数id,但url将提供字符串

  • 我们需要创建一个操作过滤器来处理在调用控制器之前传递的新参数

    public class SlugToIdAttribute : ActionFilterAttribute
    {
    
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var slug = filterContext.RouteData.Values["slug"] as string;
            if (slug != null)
            {
                //my transformed url will always end in '-1234' so i split the param on '-' and get the last portion of it. That is my id. 
                //if an id is not supplied, meaning the param is not ending in a number i will just continue and let something else handle the error
                int id;
                Int32.TryParse(slug.Split('-').Last(), out id);
                if (id != 0)
                {
                    //the controller expects an id and here we will provide it
                    filterContext.ActionParameters["id"] = id;
                }
            }
            base.OnActionExecuting(filterContext);
        }
    }
    
  • 现在,控制器将能够接受以数字结尾的非数字id,并提供其视图,而无需修改控制器的内容。我们只需要在控制器上添加filter属性,如下一步所示

    我真的不在乎产品名是否就是产品名。您可以尝试获取以下URL:

    \产品编号123

    \product\product-name-123

    \product\another-product-123

    \product\john-doe-123

    尽管URL不同,您仍然可以获得id为
    123
    的产品

  • 下一步是让控制器知道它必须使用一个特殊的文件管理器

    [SlugToId]
    public ActionResult Index(int id)
    {
    }
    

  • 它称为slug,您可以使用自定义操作筛选器根据ID查找数据库值并将其附加到路由。解释你能做什么do@StephenMuecke有趣的文章。但这似乎会接受人类可读的url来计算id。我想将id放入地址栏,然后将其更改为人类可读的id。在我看来,最好的解决方案是将你的提议(slug)和301回复混合在一起。你只需要做相反的事情。根据
    id
    route vale,查找数据库以获取slug并修改路由值(具体操作方式-例如,在地址栏中键入以下内容
    http://stackoverflow.com/questions/30071228
    看看它是否有效)@StephenMuecke被怀疑,即使如此,我还是会用一个永久移动的
    301来回答这个问题。我会更新这个问题,让你看到控制台。不确定你的意思-如果你在地址栏中输入了上面的url,它会显示这个问题,修改后的地址是
    http://stackoverflow.com/questions/30071228/manipulate-the-url-using-routing
    [SlugToId]
    public ActionResult Index(int id)
    {
    }