Pass Dictionary of routeValues to ActionLink
Asked Answered
A

5

8

All,

Getting to grips with ASP.NET MVC. So far, so good, but this one is a little nuts.

I have a view model that contains a dictionary of attributes for a hyperlink, used like this:

menu = model variable

Html.ActionLink(Html.Encode(menu.Name), Html.Encode(menu.Action), Html.Encode(menu.Controller), menu.Attributes, null)

The problem is the position of "menu.Attributes" expects an object in the form:

new  { Name = "Fred", Age=24 }

From what I can tell, this anonymous object is actually converted to a dictionary via reflection anyway BUT you can't pass a dictionary to it in the first place!!!

The Html generated for the link simply shows the dictionary type.

How on earth do I get round this? The whole point is that its general and the controller can have set the menu.Attributes previously....

Based on a post below I tried the following:

Html.ActionLink(Html.Encode(menu.Name), Html.Encode(menu.Action), Html.Encode(menu.Controller), new RouteValueDictionary(menu.Attributes), new Dictionary<string,object>())

but this still doesn't work (I guess the code internally calls the generic method that takes objects?). The above (and my original solution of passing a dictionary to the 4th paramater produces a HTML similar to this:

<a href="/EditRole?Comparer=System.Collections.Generic.GenericEqualityComparer%601%5BSystem.String%5D&amp;Count=1&amp;Keys=System.Collections.Generic.Dictionary%602%2BKeyCollection%5BSystem.String%2CSystem.String%5D&amp;Values=System.Collections.Generic.Dictionary%602%2BValueCollection%5BSystem.String%2CSystem.String%5D">EditDocumentRoles</a>

i.e. it's using reflection and working things out completely wrong...

Aliment answered 13/3, 2010 at 19:28 Comment(0)
C
9

The suggestions on how to fix worked for me in MVC3. Example usage:

IDictionary<string, object> routeValues = new Dictionary<string, object>();

routeValues.Add("EmployeeID", 1);

@Html.ActionLink("Employee Details", "EmployeeDetails", "Employee", new RouteValueDictionary(routeValues), null);
Coyne answered 1/3, 2012 at 23:29 Comment(0)
J
3

Graham,

menu.Attributes is an IDictionary<string, string> and the method expects IDictionary<string, object> right? Copy your keys and values into another dictionary where the values are of type object.

Jewelfish answered 28/6, 2010 at 18:12 Comment(1)
This was the answer. This is also the answer when creating a RouteValueDictionary too -- the contructor doesn't treat anything but Dictionary<String, Object> correctly.Holsworth
W
1

RouteValueDictionary in System.Web.Routing, actually, so yes. This class has a constructor that takes an object, or an IDictionary<string, object>. There is one overload that takes this. So you can pass a RouteValueDictionary instead.

EDIT: I think the problem is with this part:

new Dictionary<string,object>()) 

at the end; it should be null. Because, what it will do is extract the public properties of the dictionary and be used incorrectly. Let me know if changing to null fixes the issue.

Wellgrounded answered 13/3, 2010 at 20:53 Comment(7)
Hi thanks but this doesn't work either. Updated the original with some more informationAliment
What is menu.Attributes? It's pulling the properties of the dictionary and using that as the routing parameters, which is why you are getting that error.Wellgrounded
menu.Attributes is itself an IDictionary<string, string>. I understand that is it using reflection to access the properties of the dictionary and getting it wrong. I don't get why the amendment I made above, ie. creating a routevalue from the dictionary, as you suggested, still gets the reflection bit incorrect as I'm passing it a routevaluedictionaryAliment
I agree... and that is backed up with this: msdn.microsoft.com/en-us/library/cc680124.aspx.Wellgrounded
Edited the post; I think you need to pass null instead of the last dictionary<string, object> that you create as a new...Wellgrounded
Hi, thanks for the update. Unfortunately no, this doesn't work either - the same result. Maybe a bug in MVC? :pAliment
Not a bug; you are required to pass in the params in a certain way; I did get this error before, but it was a while ago and I forget all of the reasons I got it. Essentially, it's sucking in the information about the dictionary itself, rather than using the internal values.... and you are right; it would be for the routing parameters value... Microsoft gives you free source code for the MVC framework; you can use this to debug through (have to change all DLL/config references to this local copy, but it works).Wellgrounded
J
0

I am using MVC 2 and I see more than one Html.ActionLink method that takes an IDictionary as a parameter for the Html attributes. Is there some reason you can't use one of those? If you really need a shorter form of that method with some defaults, then you can write an adapter extension method on HtmlHelper.

http://msdn.microsoft.com/en-us/library/system.web.mvc.html.linkextensions.actionlink(VS.90).aspx

Perhaps I don't understand your question.

Jewelfish answered 16/6, 2010 at 20:18 Comment(0)
C
0

Space Cow.. I've lost the original Id I used to post this so cannot answer your question directly.

This was with ASP.NET MVC 1.0.

Although there was an overload that appeared to take a dictonary, the HTML generated was not the contents of the dictionary but the reflected type of the dictionary itself, basically not doing what I'd expect. There was no way in the MVC framework that I could get it to accept a predefined key/value list (e.g. in a dictionary) and for it to generate the HTML href properly. I had to create an anonymous object, which was not possible in my scenario.

Clotheshorse answered 18/6, 2010 at 22:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.