Unable to load one or more of the types in assembly 'DotNetOpenAuth, Version=3.4.5.10202, Culture=neutral, PublicKeyToken=2780ccd10d57b246'. Exceptions were thrown: System.IO.FileNotFoundException: Could not load file or assembly 'System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified. Unable to load one or more of the types in assembly 'DotNetOpenAuth, Version=3.4.5.10202, Culture=neutral, PublicKeyToken=2780ccd10d57b246'. Exceptions were thrown: System.IO.FileNotFoundException: Could not load file or assembly 'System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified. at umbraco.BusinessLogic.Utils.TypeFinder.FindClassesMarkedWithAttribute(Assembly assembly, Type attribute) at umbraco.BusinessLogic.Utils.TypeFinder.FindClassesMarkedWithAttribute(Type attribute) at umbraco.macro.GetXsltExtensionsImpl() at umbraco.cms.businesslogic.cache.Cache.GetCacheItem[TT](String cacheKey, Object syncLock, CacheItemPriority priority, CacheItemRemovedCallback refreshAction, CacheDependency cacheDependency, TimeSpan timeout, GetCacheItemDelegate`1 getCacheItem) at umbraco.macro.GetXsltExtensions() at umbraco.macro.AddMacroXsltExtensions() at umbraco.macro.GetXsltTransformResult(XmlDocument macroXML, XslCompiledTransform xslt, Dictionary`2 parameters) at umbraco.macro.loadMacroXSLT(macro macro, MacroModel model, Hashtable pageElements)
This is an issue to do with the TypeFinder static class, which uses Reflection to crawl assemblies (and referenced assemblies therein) to find classes decorated with [XsltExtension] or [RestExtension]. Because DotNetOpenAuth and ReCAPTCHA have "soft" references to System.Web.Mvc (in that they reference it, but the reference should not be called into question unless you're using the MVC-specific classes), the TypeFinder class tries to open all referenced DLLs, and get the public classes to then check for the decorative attribute. Because System.Web.Mvc is not included by default, it errors in a rather ugly fashion.
The workaround is to either include System.Web.Mvc.dll in your /bin directory, or to install ASP.NET MVC via WebPI on your server. I opt for the latter cause it's easier and avoids it happening to any other sites on the same server, but it does need patching & I've taken a look at it.
Umbraco has a mechanism to auto-discover some functionality, such as XSLT extensions, by looking for types marked with special attributes. In order to do so, it has to load each and every assembly within reach, and then recursively load each and every dependency assembly. In the past (pre-4.7 I believe) this was wrapped in a giant try...catch and every exception was ignored. This try...catch has been removed because it was hiding errors and turning debugging into a nightmare.
The drawback is that if a DLL in your BIN has some unresolved dependencies, you'll get the above error. In your case it looks like DotNetOpenAuth somewhat references System.Web.Mvc... which does not seem to be installed on your server. In other words, the entire set of DLLs in BIN has to be "consistent" ie all dependencies must be recursively resolveable.
Now, the issue is indeed rather common now that people use 4.7 more and more, and I start to wonder whether we should keep throwing exceptions, or just report the error in the trace and keep running. What do ppl think?
Edit: I wrote this then had lunch then posted it... and in the meantime Benjamin explained pretty much the same... But the question remains valid: should we stop throwing exceptions when a reference can not be resolved, and simply report the error to the trace and/or log?
@Lennart: I don't think there is a difference between a soft and a hard reference. A reference is resolved when you examine a type that depends on it. If you use DotNetOpenAuth but don't use any of the types that depend on MVC then the MVC reference will not be resolved. But since the TypeFinder wants to examine each and every type in a DLL, it _will_ examine types that depend on MVC.
I don't see how we can avoid the exception. But we could decide it's not lethal and simply report it in the trace instead of throwing.
We shouldn't throw exceptions on missing assemblies IMO. If you need a class in an assembly in your C#/.NET code then your compiler should catch the missing reference anyway. From my initial checks so far there's no way of distinguishing a "soft" reference - it's identical to any other reference, but only gets called into play when you use a class that uses the reference - e.g. ReCAPTCHA MVC controls need route-handling magic in System.Web.Mvc.
Dynamic discovery of extensions is great, but I think it should stretch to a single level - thinking about it, doesn't this mean that you're also crawling every Umbraco DLL, and don't they cross-reference each other...? By that logic, does it make this an un-necessary performance hit by searching a DLL's references? Just a thought.
Ugly as it sounds (I hate hard-coding stuff), there could be a hard-code to ignore types that inherit from classes in System.Web.Mvc... as it seems to be only this library that causes the majority of problems. Thoughts?
I think Benjamin has a point with recursive crawling & performance overhead. If there's any DLL's that contain XSLT extensions etc. they should be referenced directly, right?
If catching those exceptions would cause debugging nightmares, you could also have them thrown in debugging mode only and catch them on a release environment (although I guess most developers will work in debugging mode locally)
@Benjamin - the .NET framework somehow ensures that there is no "infinite loops" in resolving dependencies. And I don't think there is a performance issue here. In addition this only runs once when the app domain starts. Or at least it should run only once.
I don't really like the idea of hiding some types... I'd rather add a configuration option so that you can select between a) throwing and b) reporting the exception, when in debug mode--in release mode we would always report and never throw.
@Stephen I know about the dependency loop thing, but I'm wondering if there's a measured performance hit from the crawls on each library - from what I remember of the core code, it doesn't aggregate all libraries and references, then do Distinct() on the entire list... which maybe it should, prior to type-finding in each library.
Not sure I understand you... TypeFinder is type-finding in each first-level libraries ie DLLs that are in BIN. But not on dependencies. When it loads Foo.dll, if Foo.dll requires System.Web.Mvc, it will require System.Web.Mvc but it will not type-find System.Web.Mvc. So I do not see where's the perf. issue. Yet I'm posting this while also helping my 4yo Playmobil secret agents fight the enemy, so maybe I'm not paying enough attention.
Looking at TypeFinder code shows that the reported exception should show only when debugging (GlobalSettings.DebugMode == true) -- in production it should not be thrown. Anz, could you confirm you're also seeing the exception, or not seeing it, when not in debug mode?
It should be relatively easy to add an umbracoTypeFinderDoesNotThrow config option...
As for discerning a soft reference from a hard reference, it seems to me the best way would be simply to catch the TypeLoadExceptions when they're thrown, then move on. If you're trying to look at an individual type and it throws, that type is unavailable and you may move onto the next type in that assembly.
That would achieve the desired behavior, albeit with exceptions which are unavoidable.
Thanks for chipping in - I found a better way which uses LoadFrom instead of Load. I've patched this and it's awaiting a pull request back into the Umbraco core to fix it. In the meantime I've attached an updated businesslogic.dll to the ticket which works with Umbraco 4.7.1 (and 4.7.1.1), but hasn't made its' way into 4.7.2 (I believe). Upvote for 4.7.3/4.8!
Referring DotNetOpenAuth.DLL making error on all XSLTs
I just referred DotNetOpenAuth.DLL and all XSLTs are showing error..
Removing DotNetOpenAuth makes all work fine!!.. It seems like some kind of bug..Its Umbraco 4.7.1
I am on a project deadline and its DotNetOpenAuth is a must to finish it..
Plaese help.......
Here is the details using umbDebugShowTrace
Unable to load one or more of the types in assembly 'DotNetOpenAuth, Version=3.4.5.10202, Culture=neutral, PublicKeyToken=2780ccd10d57b246'. Exceptions were thrown:
System.IO.FileNotFoundException: Could not load file or assembly 'System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.
Unable to load one or more of the types in assembly 'DotNetOpenAuth, Version=3.4.5.10202, Culture=neutral, PublicKeyToken=2780ccd10d57b246'. Exceptions were thrown:
System.IO.FileNotFoundException: Could not load file or assembly 'System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.
at umbraco.BusinessLogic.Utils.TypeFinder.FindClassesMarkedWithAttribute(Assembly assembly, Type attribute)
at umbraco.BusinessLogic.Utils.TypeFinder.FindClassesMarkedWithAttribute(Type attribute)
at umbraco.macro.GetXsltExtensionsImpl()
at umbraco.cms.businesslogic.cache.Cache.GetCacheItem[TT](String cacheKey, Object syncLock, CacheItemPriority priority, CacheItemRemovedCallback refreshAction, CacheDependency cacheDependency, TimeSpan timeout, GetCacheItemDelegate`1 getCacheItem)
at umbraco.macro.GetXsltExtensions()
at umbraco.macro.AddMacroXsltExtensions()
at umbraco.macro.GetXsltTransformResult(XmlDocument macroXML, XslCompiledTransform xslt, Dictionary`2 parameters)
at umbraco.macro.loadMacroXSLT(macro macro, MacroModel model, Hashtable pageElements)
Its still a mystery to me why this keeps happening: referencing a third party assembly and running into missing MVC dependencies.
I had the same issue when referencing recaptcha, here's how I worked around it:
http://our.umbraco.org/forum/getting-started/installing-umbraco/22533-Upgrade-to-470-Recaptcha-missing-assembly-reference
Still not sure why it would require MVC..
wow!! thanks a lot.. I have read the links from your posts and it seems like its a common issue!!!
This is an issue to do with the TypeFinder static class, which uses Reflection to crawl assemblies (and referenced assemblies therein) to find classes decorated with [XsltExtension] or [RestExtension]. Because DotNetOpenAuth and ReCAPTCHA have "soft" references to System.Web.Mvc (in that they reference it, but the reference should not be called into question unless you're using the MVC-specific classes), the TypeFinder class tries to open all referenced DLLs, and get the public classes to then check for the decorative attribute. Because System.Web.Mvc is not included by default, it errors in a rather ugly fashion.
The workaround is to either include System.Web.Mvc.dll in your /bin directory, or to install ASP.NET MVC via WebPI on your server. I opt for the latter cause it's easier and avoids it happening to any other sites on the same server, but it does need patching & I've taken a look at it.
HTH,
Benjamin
Thanks Benjamin, that really explains it.
I'm not sure if its possible for the TypeFinder to distinguish soft from hard references?
Umbraco has a mechanism to auto-discover some functionality, such as XSLT extensions, by looking for types marked with special attributes. In order to do so, it has to load each and every assembly within reach, and then recursively load each and every dependency assembly. In the past (pre-4.7 I believe) this was wrapped in a giant try...catch and every exception was ignored. This try...catch has been removed because it was hiding errors and turning debugging into a nightmare.
The drawback is that if a DLL in your BIN has some unresolved dependencies, you'll get the above error. In your case it looks like DotNetOpenAuth somewhat references System.Web.Mvc... which does not seem to be installed on your server. In other words, the entire set of DLLs in BIN has to be "consistent" ie all dependencies must be recursively resolveable.
Now, the issue is indeed rather common now that people use 4.7 more and more, and I start to wonder whether we should keep throwing exceptions, or just report the error in the trace and keep running. What do ppl think?
Edit: I wrote this then had lunch then posted it... and in the meantime Benjamin explained pretty much the same... But the question remains valid: should we stop throwing exceptions when a reference can not be resolved, and simply report the error to the trace and/or log?
@Lennart: I don't think there is a difference between a soft and a hard reference. A reference is resolved when you examine a type that depends on it. If you use DotNetOpenAuth but don't use any of the types that depend on MVC then the MVC reference will not be resolved. But since the TypeFinder wants to examine each and every type in a DLL, it _will_ examine types that depend on MVC.
I don't see how we can avoid the exception. But we could decide it's not lethal and simply report it in the trace instead of throwing.
We shouldn't throw exceptions on missing assemblies IMO. If you need a class in an assembly in your C#/.NET code then your compiler should catch the missing reference anyway. From my initial checks so far there's no way of distinguishing a "soft" reference - it's identical to any other reference, but only gets called into play when you use a class that uses the reference - e.g. ReCAPTCHA MVC controls need route-handling magic in System.Web.Mvc.
Dynamic discovery of extensions is great, but I think it should stretch to a single level - thinking about it, doesn't this mean that you're also crawling every Umbraco DLL, and don't they cross-reference each other...? By that logic, does it make this an un-necessary performance hit by searching a DLL's references? Just a thought.
Benjamin
@Stephen you got there as I did! lol
Ugly as it sounds (I hate hard-coding stuff), there could be a hard-code to ignore types that inherit from classes in System.Web.Mvc... as it seems to be only this library that causes the majority of problems. Thoughts?
I think Benjamin has a point with recursive crawling & performance overhead. If there's any DLL's that contain XSLT extensions etc. they should be referenced directly, right?
If catching those exceptions would cause debugging nightmares, you could also have them thrown in debugging mode only and catch them on a release environment (although I guess most developers will work in debugging mode locally)
@Benjamin - the .NET framework somehow ensures that there is no "infinite loops" in resolving dependencies. And I don't think there is a performance issue here. In addition this only runs once when the app domain starts. Or at least it should run only once.
I don't really like the idea of hiding some types... I'd rather add a configuration option so that you can select between a) throwing and b) reporting the exception, when in debug mode--in release mode we would always report and never throw.
If that makes sense enough I can push a patch...
@Stephen I know about the dependency loop thing, but I'm wondering if there's a measured performance hit from the crawls on each library - from what I remember of the core code, it doesn't aggregate all libraries and references, then do Distinct() on the entire list... which maybe it should, prior to type-finding in each library.
Not sure I understand you... TypeFinder is type-finding in each first-level libraries ie DLLs that are in BIN. But not on dependencies. When it loads Foo.dll, if Foo.dll requires System.Web.Mvc, it will require System.Web.Mvc but it will not type-find System.Web.Mvc. So I do not see where's the perf. issue. Yet I'm posting this while also helping my 4yo Playmobil secret agents fight the enemy, so maybe I'm not paying enough attention.
Looking at TypeFinder code shows that the reported exception should show only when debugging (GlobalSettings.DebugMode == true) -- in production it should not be thrown. Anz, could you confirm you're also seeing the exception, or not seeing it, when not in debug mode?
It should be relatively easy to add an umbracoTypeFinderDoesNotThrow config option...
As for discerning a soft reference from a hard reference, it seems to me the best way would be simply to catch the TypeLoadExceptions when they're thrown, then move on. If you're trying to look at an individual type and it throws, that type is unavailable and you may move onto the next type in that assembly.
That would achieve the desired behavior, albeit with exceptions which are unavoidable.
Hi Andrew,
Thanks for chipping in - I found a better way which uses LoadFrom instead of Load. I've patched this and it's awaiting a pull request back into the Umbraco core to fix it. In the meantime I've attached an updated businesslogic.dll to the ticket which works with Umbraco 4.7.1 (and 4.7.1.1), but hasn't made its' way into 4.7.2 (I believe). Upvote for 4.7.3/4.8!
Cheers,
Benjamin
is working on a reply...