ASP.NET MVC路由上的尾部斜杠

时间:2020-03-06 14:56:19  来源:igfitidea点击:

在最新的MVC预览中,我将此路由用于旧版URL:

routes.MapRoute(
"Legacy-Firefox", // Route name
"Firefox-Extension/", // URL with parameters
new { controller = "Home", action = "Firefox", id = "" } // Parameter defaults
);

问题在于这两个URL都可以工作:
http://example.com/Firefox-Extension
http://example.com/Firefox-Extension/

我只希望第二个工作(用于SEO)。另外,当我创建到该页面的链接时,路由引擎会给我返回一个没有尾随斜杠的URL。

这是我用来生成链接的代码:

<%= Html.ActionLink("Firefox Extension", "Firefox", "Home")%>

我相信可以通过使用HTTP处理程序执行301重定向到带有斜杠的URL来解决第一个问题。但是,我想用斜杠链接到URL,我希望不必用斜杠对版本进行硬编码。

有人知道如何强制路由使用斜杠吗?

解决方案

编写链接时,应始终包含最后的斜杠。我不知道这是否适用于mvc框架(或者一般来说是URL路由),但是我知道对于静态资源,如果不加斜杠,则会增加两次请求的开销。

斜杠立即将URL标识为指向目录。无需解析文件。

同样,当我们使用URL路由时,我认为这并不适用,但是我没有对此进行研究。

在此处查看有关尾随斜杠的文章

编辑:
考虑到这一点...我认为最好不要使用斜杠,而应该尝试将其包括在内。当我们使用url路由时,我们是在使用URL直接路由到资源。与指向带有index.html或者default.aspx的目录相反,我们指向的是特定文件。

我知道差异是细微的,但最好还是对Routed Urls采取不加斜线的态度,而不是与框架抗争。

实际指向目录时,请严格使用尾部斜杠。以为我猜想,如果我们真的不喜欢,可以每次都在末尾添加一个斜杠。

如果通过RouteLink进行包装,则可以轻松解决该问题。
例如,我有一个包装方法RouteLinkEx:

public static string RouteLinkEx(this HtmlHelper helper,string text,string routeName,RouteValueDictionary rvd,object htmlAttributes)
      {

      UrlHelper uh = new UrlHelper(helper.ViewContext.RequestContext,helper.RouteCollection);
      // Add trailing slash to the url of the link
      string url = uh.RouteUrl(routeName,rvd) + "/";
      TagBuilder builder = new TagBuilder("a")
      {
        InnerHtml = !string.IsNullOrEmpty(text) ? HttpUtility.HtmlEncode(text) : string.Empty
      };
      builder.MergeAttributes(new RouteValueDictionary(htmlAttributes));
      builder.MergeAttribute("href",url);
      return builder.ToString(TagRenderMode.Normal);
      //---  
      }

如我们所见,我首先使用参数来生成URL。然后我在URL的末尾添加了" /"。然后我使用这些URL生成了完整的链接。

这是RouteLinkEx(HtmlHelper,string,string,object)的重载

public static string RouteLinkEx(this HtmlHelper helper, string text, string routeName, object routeValues)
    {

        UrlHelper uh = new UrlHelper(helper.ViewContext.RequestContext);

        // Add trailing slash to the url of the link 
        string url = uh.RouteUrl(routeName, routeValues) + "/";
        TagBuilder builder = new TagBuilder("a")
        {
            InnerHtml = !string.IsNullOrEmpty(text) ? HttpUtility.HtmlEncode(text) : string.Empty
        };
        //builder.MergeAttributes(new RouteValueDictionary(htmlAttributes));
        builder.MergeAttribute("href", url);
        return builder.ToString(TagRenderMode.Normal);
        //---   
    }

我偶然发现了这篇博客文章:

http://www.ytechie.com/2008/10/aspnet-mvc-what-about-seo.html

今天早上在StackOverflow上遇到这个问题之前。该博客文章(来自该问题的作者)对Scott Hanselman的这篇博客文章进行了追溯,并给出了以下问题的答案:

http://www.hanselman.com/blog/ASPNETMVCAndTheNewIIS7RewriteModule.aspx

我很惊讶地发现这里还没有链接,所以我添加了它。 :)

Scott的答案建议使用URL重写。

这是我的ASP.NET MVC 2版本

public static MvcHtmlString RouteLinkEx(this HtmlHelper helper, string text, RouteValueDictionary routeValues)
    {
        return RouteLinkEx(helper, text, null, routeValues, null);
    }

    public static MvcHtmlString RouteLinkEx(this HtmlHelper htmlHelper, string text, string routeName, RouteValueDictionary routeValues, object htmlAttributes)
    {
        string url = UrlHelper.GenerateUrl(routeName, null, null, null, null, null, routeValues, htmlHelper.RouteCollection, htmlHelper.ViewContext.RequestContext, false);

        var builder = new TagBuilder("a")
        {
            InnerHtml = !string.IsNullOrEmpty(text) ? HttpUtility.HtmlEncode(text) : string.Empty
        };
        builder.MergeAttributes(new RouteValueDictionary(htmlAttributes));
        // Add trailing slash to the url of the link
        builder.MergeAttribute("href", url + "/");
        return MvcHtmlString.Create(builder.ToString(TagRenderMode.Normal));
    }