Friday, July 24, 2015

ASP.NET MVC Renders Length=4 in Html.ActionLink

You might have noticed this really strange behavior in ASP.NET MVC4 (and possibly other versions too) where @Html.ActionLink inexplicably appends the rendered links with "?Length=4". For example,

@Html.ActionLink("My App Header", "Index", "Home", new { //your html attributes })

becomes

<a href="/MyApp/?Length=4">My App Header</a>

This seems to make no sense at all, but there indeed is an explanation but before we get to that, let's first see a few ways of fixing it.

Solution 1 - Just add a null paramter after the Controller name parameter. Sp, change

@Html.ActionLink("My App Header", "Index", "Home", new { //your html attributes }) to

@Html.ActionLink("My App Header", "Index", "Home", null, new { //your html attributes })

Solution 2 - Use @Url.Action instead. So, basically change

@Html.ActionLink("My App Header", "Index", "Home", new { //your html attributes }) to

<a href="@Url.Action("Index", "Home")" //your html attributes>My App Header</a>

So, now with the solutions out of the way, here is the explanation for just where the Length=4 thing comes from - Basically the @Html.ActionLink method that your code runs in these cases is defined as follows -

public static string ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, object routeValues, object htmlAttributes)

So, when ASP.NET MVC engine comes across a call like @Html.ActionLink("My App Header", "Index", "Home", new { //your html attributes }), it takes "Home" as the routeValues parameter instead! The way routValues parameter works is that it looks for all public properties in the passed object and uses them for routing as per the routing configuratin. In the case of "Home" object, which is a string, the only public property is "Length" Now, since usually you don't have a "Length" route property in your configuration, it just appends the property name and value to querystring instead. Yes, the ASP.NET MVC Convention over Configuration at work here!! This is actually kinda cool when you think about it!! Now, as for why adding null in @Html.Action fixes it, it's because the null object doesn't have a public property (duh!). As a fun experiment, you could try adding another paramter to @Url.Action and you'll find the Length=4 querystring parameter in your rendered links again!

2 comments:

  1. We had this problem too, but we hadn't changed the view from what Visual Studio generated for us. It seems like it must have been wrong in the template.

    ReplyDelete