加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net-mvc – 使用路由操作URL

发布时间:2020-12-16 07:41:40 所属栏目:asp.Net 来源:网络整理
导读:在我的网站中,我定义了以下路线: routes.MapRoute( name: "Specific Product",url: "product/{id}",defaults: new { controller = "",action = "Index",id = UrlParameter.Optional }); 这样我希望客户能够添加产品的ID并转到产品页面. SEO顾问说,如果我们
在我的网站中,我定义了以下路线:

routes.MapRoute(
   name: "Specific Product",url: "product/{id}",defaults: new { controller = "",action = "Index",id = UrlParameter.Optional }
);

这样我希望客户能够添加产品的ID并转到产品页面.

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

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

要么

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

当然描述存储在db中,我不能用url重写(或者我可以吗?)

我应该在我的控制器上添加重定向(这似乎可以完成工作,但感觉不对)

在我检查的几个网站上,他们确实以301 Moved Permanently回复.这真的是最好的方法吗?

UPDATE

根据Stephen Muecke的评论,我检查了SO上发生了什么.

建议的URL是我自己的Manipulate the url using routing,我打开控制台看到任何重定向.这是一个截图:

解决方法

所以,首先非常特别感谢@StephenMuecke给出了slug的提示以及他建议的网址.

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

我的目标是让用户输入一个网址:

/product/123

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

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

我检查了几个有这种行为的网站,似乎在我检查的所有内容中都使用了301 Moved Permanently响应.即使如我的问题所示,使用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类来处理重定向.这实际上是here的直接副本

public class RedirectHandler : IHttpHandler
{
    private string newUrl;

    public RedirectHandler(string newUrl)
    {
        this.newUrl = newUrl;
    }

    public bool IsReusable
    {
        get { return true; }
    }

    public void ProcessRequest(HttpContext httpContext)
    {
        httpContext.Response.Status = "301 Moved Permanently";
        httpContext.Response.StatusCode = 301;
        httpContext.Response.AppendHeader("Location",newUrl);
        return;
    }
}

通过这两个类,我可以将产品ID转换为SEO友好的URL.

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

>从路线调用SlugRouteHandler类

routes.MapRoute(
   name: "Specific Product",url: "product/{slug}",defaults: new { controller = "Product",action = "Index" }
).RouteHandler = new SlugRouteHandler();

以下是他在评论中提到的link @StephenMuecke的使用.

我们需要找到一种方法将新的SEO友好URL映射到我们的实际控制器.我的控制器接受一个整数id,但url将提供一个字符串.

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

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属性,如下一步所示.

我真的不在乎产品名称是否实际上是产品名称.您可以尝试获取以下网址:

product123

productproduct-name-123

productanother-product-123

productjohn-doe-123

你会得到id为123的产品,尽管网址不同.

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

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读