views:

2232

answers:

5

In the latest MVC preview, I'm using this route for a legacy URL:

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

The problem is that both of these URL's work: http://mysite.com/Firefox-Extension http://mysite.com/Firefox-Extension/

I only want the second to work (for SEO). Also, when I create a link to that page, the routing engine gives me back a URL without a trailing slash.

This is the code I'm using to generate the link:

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

I believe can fix the first problem by using an HTTP handler to do a 301 redirect to the URL with the trailing slash. However, I want to link to the URL with the trailing slash, and I'm hoping to not have to hard-code the version with the slash.

Anyone know how to force the route to use a trailing slash?

+2  A: 

When you write your links, you should always include the final slash. I don't know if this applies to the mvc framework (or URL Routing in general), but I know that for static resources, if you don't put the slash in you add a slight overhead as the request gets done twice.

The slash immediately identifies the url as pointing to a directory. No need to parse files.

Again, I don't believe this applies when you use URL routing, but I haven't looked into it.

Check HERE for an article about the trailing slash

edit: Upon thinking about this... I think it's probably better to leave off the slash, instead of trying to include it. When you're using url routing, you're using the URL to route directly to a resource. As opposed to pointing to a directory with an index.html or default.aspx, you're pointing to a specific file.

I know the difference is subtle, but it may be better to stick to the non-slash for Routed Urls, rather than fight with the framework.

Use a trailing slash strictly when you're actually pointing to a directory. Thought I guess you could just append a slash to the end every time if you really didn't like it.

Atømix
I agree, for new sites that's how I would do it. The problem is, I have an existing site I'm trying to convert.
Jason Young
I probably wouldn't spend too much time on it. My guess is that Google is smart enough these days not to give you an SEO hit.
Atømix
+1  A: 

If you have a wrapper over RouteLink than there is an easy solution of the problem. For example, I had a wrapper method 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);
      //---  
      }

As you see I used parameters to generate URL first. Then I added "/" at the end of the URL. and then I generated complete link using those URL.

murad
A: 

Here a overload for 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);
        //---   
    }
Sky
A: 

I happened across this blog post:

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

this morning before running into this question on StackOverflow. That blog post (from the author of this question) has a trackback to this blog post from Scott Hanselman with an answer to this question:

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

I was surprised to find no link from here to there yet, so I just added it. :)

Scott's answer suggests using URL Rewriting.

Michael Maddox
A: 

Here is my version for 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));
    }
McLovin