An item with the same key has already been added

Jun 13, 2011 at 12:27 AM
Edited Jun 13, 2011 at 12:28 AM

I've just ran into this nasty exception that I can't get rid off. It's a simple sitemap inside an area folder and I have two providers registered in web.config and it is picking them up fine. It's just this error that I can't get rid off despite having changed my routes all over and again and nothing helps.

I saw there's something about this exception that was corrected in 3.1 RC build so I installed it but my exception remains.

What specifically was changed about this exception or where was did this exception most likely to occur that you spotted it and decided to fix it? Coz I don't know whether it is my code or a bug still remains in your codebase..

Thank you Maarten

Coordinator
Jun 14, 2011 at 9:16 AM

Exception? Stacktrace? ...?

Jun 14, 2011 at 10:44 AM

Exception occurs in the get() property of UrlHelper where he tries to construct an action URL with the same parameters twice:

An item with the same key has already been added.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.ArgumentException: An item with the same key has already been added.

Source Error:

Line 39: 			<nav id="menu">
Line 40: 			@Html.MvcSiteMap("AdminSiteMapProvider").Menu()
Line 41: 			@Html.MvcSiteMap("AdminSiteMapProvider").SiteMapPath()
Line 42: 			</nav>


Source File: e:\dsh2011\dsh2011\Areas\Admin\Views\Shared\_AdminLayout.cshtml    Line: 40

Stack Trace:

[ArgumentException: An item with the same key has already been added.]
   System.ThrowHelper.ThrowArgumentException(ExceptionResource resource) +52
   System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add) +9382923
   System.Collections.Generic.Dictionary`2..ctor(IDictionary`2 dictionary, IEqualityComparer`1 comparer) +221
   System.Web.Routing.RouteValueDictionary..ctor(IDictionary`2 dictionary) +44
   MvcSiteMapProvider.DefaultSiteMapNodeUrlResolver.ResolveUrl(MvcSiteMapNode mvcSiteMapNode, String area, String controller, String action, IDictionary`2 routeValues) in c:\Projects\Codeplex\TFS10\mvcsitemap\Branches\3.1.0\src\MvcSiteMapProvider\MvcSiteMapProvider\DefaultSiteMapNodeUrlResolver.cs:86
   MvcSiteMapProvider.MvcSiteMapNode.get_Url() in c:\Projects\Codeplex\TFS10\mvcsitemap\Branches\3.1.0\src\MvcSiteMapProvider\MvcSiteMapProvider\MvcSiteMapNode.cs:284
   MvcSiteMapProvider.AuthorizeAttributeAclModule.IsAccessibleToUser(IControllerTypeResolver controllerTypeResolver, DefaultSiteMapProvider provider, HttpContext context, SiteMapNode node) in c:\Projects\Codeplex\TFS10\mvcsitemap\Branches\3.1.0\src\MvcSiteMapProvider\MvcSiteMapProvider\AuthorizeAttributeAclModule.cs:45
   MvcSiteMapProvider.DefaultAclModule.IsAccessibleToUser(IControllerTypeResolver controllerTypeResolver, DefaultSiteMapProvider provider, HttpContext context, SiteMapNode node) in c:\Projects\Codeplex\TFS10\mvcsitemap\Branches\3.1.0\src\MvcSiteMapProvider\MvcSiteMapProvider\DefaultAclModule.cs:61
   MvcSiteMapProvider.DefaultSiteMapProvider.IsAccessibleToUser(HttpContext context, SiteMapNode node) in c:\Projects\Codeplex\TFS10\mvcsitemap\Branches\3.1.0\src\MvcSiteMapProvider\MvcSiteMapProvider\DefaultSiteMapProvider.cs:180
   System.Web.SiteMapNode.IsAccessibleToUser(HttpContext context) +17
   MvcSiteMapProvider.Web.Html.MenuHelper.BuildModel(MvcSiteMapHtmlHelper helper, SiteMapNode startingNode, Boolean startingNodeInChildLevel, Boolean showStartingNode, Int32 maxDepth, Boolean drillDownToCurrent) in c:\Projects\Codeplex\TFS10\mvcsitemap\Branches\3.1.0\src\MvcSiteMapProvider\MvcSiteMapProvider\Web\Html\MenuHelper.cs:280
   MvcSiteMapProvider.Web.Html.MenuHelper.Menu(MvcSiteMapHtmlHelper helper, String templateName, SiteMapNode startingNode, Boolean startingNodeInChildLevel, Boolean showStartingNode, Int32 maxDepth, Boolean drillDownToCurrent) in c:\Projects\Codeplex\TFS10\mvcsitemap\Branches\3.1.0\src\MvcSiteMapProvider\MvcSiteMapProvider\Web\Html\MenuHelper.cs:234
   MvcSiteMapProvider.Web.Html.MenuHelper.Menu(MvcSiteMapHtmlHelper helper, SiteMapNode startingNode, Boolean startingNodeInChildLevel, Boolean showStartingNode, Int32 maxDepth, Boolean drillDownToContent) in c:\Projects\Codeplex\TFS10\mvcsitemap\Branches\3.1.0\src\MvcSiteMapProvider\MvcSiteMapProvider\Web\Html\MenuHelper.cs:124
   MvcSiteMapProvider.Web.Html.MenuHelper.Menu(MvcSiteMapHtmlHelper helper) in c:\Projects\Codeplex\TFS10\mvcsitemap\Branches\3.1.0\src\MvcSiteMapProvider\MvcSiteMapProvider\Web\Html\MenuHelper.cs:31
   ASP._Page_Areas_Admin_Views_Shared__AdminLayout_cshtml.Execute() in e:\dsh2011\dsh2011\Areas\Admin\Views\Shared\_AdminLayout.cshtml:40

 


Coordinator
Jun 14, 2011 at 11:49 AM

Ok this is a strange one. Seems like an error in ASP.NET MVC itself?

Jun 14, 2011 at 12:23 PM

Hm, don't know really, could be.

This is how my web.config looks like:

		<siteMap defaultProvider="MvcSiteMapProvider" enabled="true">
			<providers>
				<clear />
				<add name="MvcSiteMapProvider" type="MvcSiteMapProvider.DefaultSiteMapProvider, MvcSiteMapProvider" siteMapFile="~/Mvc.Sitemap" securityTrimmingEnabled="true" cacheDuration="5" enableLocalization="true" scanAssembliesForSiteMapNodes="true" includeAssembliesForScan="" excludeAssembliesForScan="" attributesToIgnore="visibility" nodeKeyGenerator="MvcSiteMapProvider.DefaultNodeKeyGenerator, MvcSiteMapProvider" controllerTypeResolver="MvcSiteMapProvider.DefaultControllerTypeResolver, MvcSiteMapProvider" actionMethodParameterResolver="MvcSiteMapProvider.DefaultActionMethodParameterResolver, MvcSiteMapProvider" aclModule="MvcSiteMapProvider.DefaultAclModule, MvcSiteMapProvider" siteMapNodeUrlResolver="MvcSiteMapProvider.DefaultSiteMapNodeUrlResolver, MvcSiteMapProvider" siteMapNodeVisibilityProvider="MvcSiteMapProvider.DefaultSiteMapNodeVisibilityProvider, MvcSiteMapProvider" siteMapProviderEventHandler="MvcSiteMapProvider.DefaultSiteMapProviderEventHandler, MvcSiteMapProvider" />
				<add name="AdminSiteMapProvider" type="MvcSiteMapProvider.DefaultSiteMapProvider, MvcSiteMapProvider" siteMapFile="~/Areas/Admin/Admin.Sitemap" securityTrimmingEnabled="true" cacheDuration="5" enableLocalization="true" scanAssembliesForSiteMapNodes="true" includeAssembliesForScan="" excludeAssembliesForScan="" attributesToIgnore="visibility" nodeKeyGenerator="MvcSiteMapProvider.DefaultNodeKeyGenerator, MvcSiteMapProvider" controllerTypeResolver="MvcSiteMapProvider.DefaultControllerTypeResolver, MvcSiteMapProvider" actionMethodParameterResolver="MvcSiteMapProvider.DefaultActionMethodParameterResolver, MvcSiteMapProvider" aclModule="MvcSiteMapProvider.DefaultAclModule, MvcSiteMapProvider" siteMapNodeUrlResolver="MvcSiteMapProvider.DefaultSiteMapNodeUrlResolver, MvcSiteMapProvider" siteMapNodeVisibilityProvider="MvcSiteMapProvider.DefaultSiteMapNodeVisibilityProvider, MvcSiteMapProvider" siteMapProviderEventHandler="MvcSiteMapProvider.DefaultSiteMapProviderEventHandler, MvcSiteMapProvider" />
			</providers>
		</siteMap>

The problem is with the second (Admin) provider. The provider correctly loads the sitemap file and all of the routes registered both in global.asax.cs and AdminAreaRegistration.cs.
When I debugged I also noticed that in this line 
                returnValue = UrlHelper.Action(action, controller, new RouteValueDictionary(routeValues));

the routeValues object contains 4 items where three are "action", "controller" and "area" with "area" being empty string and another "Area" route value correctly holding the "Admin" value. Could this have anything to do with it? 
What about your code that check for route values and uses .Contains("area")? Shouldn't this be made caseinsensitive? Because I think various casings of those three names for route values could occur throught an ASP.NET MVC application without us having control of it all the time.
Coordinator
Jun 29, 2011 at 12:15 PM

Oh dear, more MVC area madness :-) Seriously feel MS as just hacked this in on various places regarding the struggle for me to cover every edge case. I will see if I can do a check on this.