Search code examples
c#asp.net-mvcrazoractionlink

Unable to pass a native value in ActionLink under Razor while POCO instances work great


First I thought that I'm using the wrong overload again (a very common gotcha in the API - everybody trips over that one). But wouldn't you know? That's not it. I actually had the HTML attributes parameter too and I verified with intellisense that it's the route values I'm entering.

@Html.ActionLink("Poof", "Action", "Home", 10, new { @class = "nav-link" })

Nevertheless, it seem that the receiving method below only sees null and crashes as it can't make an integer out of it.

public ActionResult Record(int count) { ... }

I've tried a few things: changed parameter type to int? and string (the program stops crashing but the value is still null). I've tested to package the passed value as an object (with/without @).

@Html.ActionLink("Poof", "Record", "Home", 
  new { count = "bamse" }, 
  new { @class = "nav-link" })

I can see that the anchor produced has my value as a query string, so the changes are there. However, I still get null only in the method.

What am I missing?

The weird thing is that the following works fine.

@Html.ActionLink("Poof", "Record", "Home", 
  new Thing(), 
  new { @class = "nav-link" })

public ActionResult Record(Thing count) { ... }

Solution

  • Your using the overload of @Html.ActionLink() that expects the 4th parameter to be typeof object. Internally the method builds a RouteValueDictionary by using the .ToString() value of each property in the object.

    In your case your 'object' (an int) has no properties, so no route values are generated and the url will be just /Home/Action(and you program crashes because your method expects a non null parameter).

    If for example you changed it to

    @Html.ActionLink("Poof", "Action", "Home", "10", new { @class = "nav-link" })
    

    i.e. quoting the 4th parameter, the url would now be /Home/Action?length=2 because typeof string has a property length and there a 2 characters in the value.

    In order to pass a native value you need to use the format

    @Html.ActionLink("Poof", "Action", "Home", new { count = 10 }, new { @class = "nav-link" })
    

    Which will generate /Home/Action?count=10 (or /Home/Action/10 if you create a specific route definition with Home/Action/{count})

    Note also that passing a POCO in your case only works correctly because your POCO contains only value type properties. If for example, it also contained a property which was (say) public List<int> Numbers { get; set; } then the url created would include ?Numbers=System.Collections.Generic.List[int] (and binding would fail) so be careful passing complex objects in an action link