Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

YSOD - An item with the same key has already been added #18

Closed
DanAtkinson opened this issue Jul 27, 2011 · 15 comments
Closed

YSOD - An item with the same key has already been added #18

DanAtkinson opened this issue Jul 27, 2011 · 15 comments

Comments

@DanAtkinson
Copy link
Contributor

Below is the following error I receive when I have added the cassette nuget package:

  • Cassette.0.5.3
  • Cassette.Web.0.5.2

No changes have been made and no scripts have been referenced yet

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:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:

[ArgumentException: An item with the same key has already been added.]
   Cassette.Web.ExceptionCachedManager.CreatePageAssetManager(HttpContextBase httpContext) +92
   Cassette.Web.CassetteHttpModule.b__0(Object sender, EventArgs e) +173
   System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +80
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +266

Many thanks, Dan Atkinson

@andrewdavey
Copy link
Owner

Hmm, perhaps I forgot to push Cassette.Web 0.5.3 to match the core library. I've just pushed it now. Please try updating to that version.

@DanAtkinson
Copy link
Contributor Author

Hi Andrew,

Alas, no dice. I updated to 0.5.3 but the same problem occurred. There was also an update to AjaxMin which I installed afterwards, also to no avail.

Thanks, Dan

@andrewdavey
Copy link
Owner

It could be the web.config transform screwing things up. Take a look at web.config. Can you paste in the <cassette> section here?

Also, there may be a conflict with AjaxMin since Cassette still targets an older version. You will probably need an assembly binding redirect for it.

@DanAtkinson
Copy link
Contributor Author

Hi Andrew, There are no transforms on this particular web.config. If you let me know which version of AjaxMin to use, then I can set the binding redirect, test and feedback.

I haven't added anything to the views yet, but in any case, when I do, the same problem occurs.

The cassette section (unmodified after install) is below:

<cassette moduleMode="OffInDebug">
  <!-- moduleMode options:
      OffInDebug => Modules are used when web application is not in debug mode
      On => Modules are always used
      Off => Modules are not used
     
     Cassette is all about defining "modules" of assets.
     So in production mode your application serves as few files as possible.
     
     Three types of module are provided by Cassette: scripts, styles and html templates.
     The modules are defined in the following sub-sections...
  -->
  <scripts>
    <!-- Script modules contain .js and .coffee files. 
       So make sure you DELETE ALL minified JS files now! Cassette will minify for you.          
    -->
    <!-- This creates a single module containing everything in "Scripts": -->
    <add path="Scripts" />
    <!-- However, it's a good idea to separate your scripts into folders e.g. 
    <add path="Scripts/lib" />  for jQuery and other third party script etc
    <add path="Scripts/app" />  for your application specific code
    etc...
    
    Alternatively, to define a module for each immediate sub-folder of Scripts,
    you can use a single <add/> with a path ending in "/*" e.g.
    <add path="Scripts/*" />
    -->
  </scripts>
  <styles>
    <!-- Style modules contain .css and .less files. -->
    <!-- This creates a single module containing everything in "Content": -->
    <add path="Content" />
    <!-- Alternatively you can separate your stylesheets into modules by using folders
       It works the same as the <scripts> section above.
    -->
  </styles>
  <htmlTemplates>
    <!-- Html template modules contain .htm and .html files. -->
  </htmlTemplates>
</cassette>

Many thanks, Dan

@andrewdavey
Copy link
Owner

AjaxMin v4.13

Your exception stack trace is unfortunately from when it is re-thrown. If possible tell VS to break on all thrown CLR exceptions (Debug > Exceptions...). Then see if you can grab the original stack trace.

Also, is this happening in a new project, or one that was using an older version of Cassette?

@DanAtkinson
Copy link
Contributor Author

Andrew,

I've stepped through it without success. It leaves the application start and then falls over. Even with CLR exceptions being set to thrown, no exception is ever caught.

This isn't a new project (about two years old), and it wasn't using an older version of cassette or knapsack when I first installed it.

Other nuget packages installed include Elmah, Glimpse and Ninject. Also, redirecting the AjaxMin version to 4.13 makes no difference.

Thanks, Dan

@andrewdavey
Copy link
Owner

Okay, we'll have to try some more serious debugging. Grab the Cassette source code and add the Cassette and Cassette.Web projects to your solution. (Removing the nuget based Cassette.Web references.) Change your web app to reference these local projects.

Then you can put a break point in: Cassette.Web/SingletonCassetteApplicationContainer.cs line 40 (where it creates the CassetteApplication object).

Does that get us any closer to the real exception?

@tkarpinski
Copy link

Here's the exception I get when debugging (I've run into the same issue)

   at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
   at System.Linq.Enumerable.ToDictionary[TSource,TKey](IEnumerable`1 source, Func`2 keySelector, IEqualityComparer`1 comparer)
   at Cassette.ModuleBuilding.UnresolvedModule.OrderScriptsByDependency(Asset[] assets) in c:\Users\tkarpinski\projects\cassette\src\Cassette\ModuleBuilding\UnresolvedModule.cs:line 116
   at Cassette.ModuleBuilding.UnresolvedModule..ctor(String path, UnresolvedAsset[] assets, String location, Boolean isAssetOrderFixed) in c:\Users\tkarpinski\projects\cassette\src\Cassette\ModuleBuilding\UnresolvedModule.cs:line 40
   at Cassette.ModuleBuilding.UnresolvedModuleBuilder.Build(String relativeModulePath, String location) in c:\Users\tkarpinski\projects\cassette\src\Cassette\ModuleBuilding\UnresolvedModuleBuilder.cs:line 32
   at Cassette.Assets.HtmlTemplates.HtmlTemplateModuleContainerBuilder.<>c__DisplayClass2.b__0(Tuple`2 x) in c:\Users\tkarpinski\projects\cassette\src\Cassette\Assets\HtmlTemplates\HtmlTemplateModuleContainerBuilder.cs:line 17
   at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
   at System.Linq.Enumerable.WhereEnumerableIterator`1.MoveNext()
   at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at Cassette.ModuleBuilding.UnresolvedModule.ResolveAll(IEnumerable`1 unresolvedModules) in c:\Users\tkarpinski\projects\cassette\src\Cassette\ModuleBuilding\UnresolvedModule.cs:line 58
   at Cassette.Assets.HtmlTemplates.HtmlTemplateModuleContainerBuilder.Build() in c:\Users\tkarpinski\projects\cassette\src\Cassette\Assets\HtmlTemplates\HtmlTemplateModuleContainerBuilder.cs:line 18
   at Cassette.CassetteApplicationBase.BuildModuleContainer(ModuleContainerBuilder builder, ModuleCollection modules) in c:\Users\tkarpinski\projects\cassette\src\Cassette\CassetteApplicationBase.cs:line 178
   at Cassette.CassetteApplicationBase.BuildHtmlTemplateModuleContainer(IsolatedStorageFile storage, CassetteSection config) in c:\Users\tkarpinski\projects\cassette\src\Cassette\CassetteApplicationBase.cs:line 164
   at Cassette.CassetteApplicationBase..ctor(CassetteSection configuration, String appDomainAppPath, String appDomainAppVirtualPath, IsolatedStorageFile storage) in c:\Users\tkarpinski\projects\cassette\src\Cassette\CassetteApplicationBase.cs:line 44
   at Cassette.Web.CassetteApplication..ctor() in C:\Users\tkarpinski\projects\cassette\src\Cassette.Web\CassetteApplication.cs:line 16
   at Cassette.Web.SingletonCassetteApplicationContainer.CreateManager() in C:\Users\tkarpinski\projects\cassette\src\Cassette.Web\SingletonCassetteApplicationContainer.cs:line 40

@DanAtkinson
Copy link
Contributor Author

Hi Andrew,

The stack trace from the caught exception on line 40 is as follows:

   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
   at System.Linq.Enumerable.ToDictionary[TSource,TKey](IEnumerable`1 source, Func`2 keySelector, IEqualityComparer`1 comparer)
   at Cassette.ModuleBuilding.UnresolvedModule.OrderScriptsByDependency(Asset[] assets) in D:\Cassette\src\Cassette\ModuleBuilding\UnresolvedModule.cs:line 116
   at Cassette.ModuleBuilding.UnresolvedModule..ctor(String path, UnresolvedAsset[] assets, String location, Boolean isAssetOrderFixed) in D:\Cassette\src\Cassette\ModuleBuilding\UnresolvedModule.cs:line 40
   at Cassette.ModuleBuilding.UnresolvedModuleBuilder.Build(String relativeModulePath, String location) in D:\Cassette\src\Cassette\ModuleBuilding\UnresolvedModuleBuilder.cs:line 32
   at Cassette.Assets.HtmlTemplates.HtmlTemplateModuleContainerBuilder.<>c__DisplayClass2.b__0(Tuple`2 x) in D:\Cassette\src\Cassette\Assets\HtmlTemplates\HtmlTemplateModuleContainerBuilder.cs:line 17
   at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
   at System.Linq.Enumerable.WhereEnumerableIterator`1.MoveNext()
   at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at Cassette.ModuleBuilding.UnresolvedModule.ResolveAll(IEnumerable`1 unresolvedModules) in D:\Cassette\src\Cassette\ModuleBuilding\UnresolvedModule.cs:line 58
   at Cassette.Assets.HtmlTemplates.HtmlTemplateModuleContainerBuilder.Build() in D:\Cassette\src\Cassette\Assets\HtmlTemplates\HtmlTemplateModuleContainerBuilder.cs:line 18
   at Cassette.CassetteApplicationBase.BuildModuleContainer(ModuleContainerBuilder builder, ModuleCollection modules) in D:\Cassette\src\Cassette\CassetteApplicationBase.cs:line 178
   at Cassette.CassetteApplicationBase.BuildHtmlTemplateModuleContainer(IsolatedStorageFile storage, CassetteSection config) in D:\Cassette\src\Cassette\CassetteApplicationBase.cs:line 164
   at Cassette.CassetteApplicationBase..ctor(CassetteSection configuration, String appDomainAppPath, String appDomainAppVirtualPath, IsolatedStorageFile storage) in D:\Cassette\src\Cassette\CassetteApplicationBase.cs:line 44
   at Cassette.Web.CassetteApplication..ctor() in D:\Cassette\src\Cassette.Web\CassetteApplication.cs:line 16
   at Cassette.Web.SingletonCassetteApplicationContainer.CreateManager() in D:\Cassette\src\Cassette.Web\SingletonCassetteApplicationContainer.cs:line 40

Thanks, Dan

@andrewdavey
Copy link
Owner

Thanks guys, that's narrowed things down. Can you see what assets are being sent to UnresolvedModule.OrderScriptsByDependency ? Somehow a duplicate file name is getting picked up.

@tkarpinski
Copy link

it is because LoadAllFilesInModule returns file.html for when searching extension .htm and .html. Directory.EnumerateFiles takes a pattern - file.html matches *.htm and *.html

@andrewdavey
Copy link
Owner

Good catch @tkarpinski . I can't fix the package right now and I'm away over the weekend. For now, make this change to UnresolvedModuleBuilder.cs

IEnumerable<UnresolvedAsset> LoadAssetByFindingFiles(string modulePath)
{
    return fileExtensions
        .SelectMany(
            extension => LoadAllFilesInModule(modulePath, extension)
        )
        .Distinct() // <--- Add this call
        .Where(ShouldNotIgnoreAsset)
        .Select(NormalizePathSlashes)
        .Select(LoadAsset);
}

@DanAtkinson
Copy link
Contributor Author

Thanks Andrew and Tod for your help on this issue.

I'll leave it until the Nuget package is deployed to check again.

Many thanks, Dan

@andrewdavey
Copy link
Owner

Cassette.Web v0.5.4 should fix this problem. Please update and let me know. Thanks.

@DanAtkinson
Copy link
Contributor Author

Hi Andrew, I can confirm v0.5.4 doesn't YSOD anymore.

Many thanks! Dan

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants