I have multiple projects in my solution. Each project references other projects. The dlls are quite big and I don't want them to be included in the bin of every project that references it.
What are my options? Ideally I'd like to place them in one location and reference that without needing to include them in my bin folder for each project. The only location I can think of is the GAC. Are there any ideas/suggestions on how you have gotten around this?
Is it possible to use probing paths? Anyone used this before/point me to a tutorial?
I've tried probing paths, get an error when running the application, is this not set up correctly? I've placed my dlls I wish to load from this path in the C:\Projects\myProject\bin folder. And set copy to false in the reference
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="C:\Projects\myProject\bin"/>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
</assemblyBinding>
Thanks
I guess what you prefer, is turning off CopyLocal when referencing assemblies in Visual Studio
The steps could be:
Open Solution Explorer
Right click at the reference item (project or assembly)
Select Properties in the context menu.
Set CopyLocal to False (default is true)
Then the references won't be copied to your project\bin\debug or etc.
UPDATE
You still need to copy your dependency to the same folder, or GAC, or probing paths to run your application.
That is how .Net resolve the assemblies references.
You may refer to How the Runtime Locates Assemblies.
UPDATE 1
MSDN Specifying an Assembly's Location
Using the <probing> Element
The runtime locates assemblies that do not have a code base by probing. For more information about probing, see How the Runtime Locates Assemblies.
You can use the element in the application configuration file to specify subdirectories the runtime should search when locating an assembly. The following example shows how to specify directories the runtime should search.
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="bin;bin2\subbin;bin3"/>
</assemblyBinding>
</runtime>
</configuration>
The privatePath attribute contains the directories that the runtime should search for assemblies. If the application is located at C:\Program Files\MyApp, the runtime will look for assemblies that do not specify a code base in C:\Program Files\MyApp\Bin, C:\Program Files\MyApp\Bin2\Subbin, and C:\Program Files\MyApp\Bin3. The directories specified in privatePath must be subdirectories of the application base directory.
You can add referenced libraries to the output folder of start up project only:
1) Right click on starting project, "Add", "Existing Item". Or [Shift]+[Alt]+[A] combination in VS2010 with defaults.
2) Change type selector to "All files (*)", find and select your library.
3) Change "Add" selector to "Add As Link" and press it.
4) Select a link just added to a project, and in Properties window set "Copy to Output Directory" to "Copy always". Now, each time you building the solution, this library will be copied to the output folder of your startup project.
5) If you want to restrict copying this dll to the output of project that uses it, right-click on reference in that project, and in Properties window set "Copy Local" to false.
Implications:
The only place where your referenced dll's will appear will be your start-up project's output directory.
Disadvantages:
If you'll change your start-up project, you'll need to add all the links to it again.
Start-up project directory in Solution Explorer becomes messy.
Related
I have a problem regarding NewtonSoft.
I have a solution with 3 projects for example. Project A has reference points to Project B and Project C, Project B also has reference points to Project C. Both B and C has NewtonSoft assembly. Project C has function to get JsonMediaTypeFormatter:
new JsonMediaTypeFormatter()
the function is called by all three project. Both Project B and C can call the function without any problem. But when project A calls the function, it throws error:
Method not found: 'Void Newtonsoft.Json.Serialization.DefaultContractResolver.set_IgnoreSerializableAttribute(Boolean)'
Something I notice that even project A does not have NewtonSoft reference, when project is built, the Newtonsoft.json.dll is copied to its bin\Debug folder. I guess it is because of Newtonsoft assembly is set to true for Copy Local optoin in both project B and C. If I manually delete this dll from Project A's bin\Debug folder, problem solved.
My question is why project A can hit the exception, and is there any solution except manually delete Newtonsoft dll from project A's bin\Debug folder? Set Copy Local to false is not a option because it will prevent dll deploying to their own bin folder for project B and C too.
Any suggestion would be appreciated.
Update
Here is my code snippet
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using System.Net.Http.Formatting;
var jsonSerializerSettings = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
var dateConverter = new IsoDateTimeConverter
{
DateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"
};
jsonSerializerSettings.Converters.Add(dateConverter);
var formatter = new JsonMediaTypeFormatter
{
//SerializerSettings = jsonSerializerSettings
};
If I comment out SerializerSettings, it works fine.
If I uncomment this line, application will return such issue.
If I just pass in blank setting to it
var formatter = new JsonMediaTypeFormatter
{
//SerializerSettings = new JsonSerializerSettings{}
};
I got error:
Method not found: 'Void System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.set_SerializerSettings(Newtonsoft.Json.JsonSerializerSettings)'
I think it may be related to different System.Net.Http.Formatting references inside projects, but I checked reference setting, they are all point to file
packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll
This code resides in Project C. It only failed when called by Project A, project B and C can call it without any problem. Once I remove NewtonSoft.Json.dll from Project A bin\Debug folder, it works in project A calls too.
Do you know what happened? and how can I check if there still have different reference version conflicit in project?
Thanks,
Here I finally got problem solved.
The reaon for this issue is that in project A, there is a reference library points to System.Net.Http.Formatting (5.2.3.0), which depends on Newtonsoft Joson version 6.0.0.0. You can check this on Assembly Explorer. I updated Newtonsoft to 8.0.0.0 recently and project B and C are referencing this version. When project is built, the Newtonsoft 8.0 has been copy to project A's output folder based on prject B and C (Copy Local is set to true). when application is running, it will throw error
System.IO.FileLoadException : Could not load file or assembly 'Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
or in my debug mode, it throws
{"The 'CreateJsonSerializer' method threw an exception when attempting to create a JSON serializer."}
Solution:
Add app.config file in project A, including setting below, to redirect system assembly binding to correct NewtonSoft version
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
</dependentAssembly>
</assemblyBinding>
The reason project B can call project C successfully is that it has this redirect on its web.config file.
Thanks,
I would clean up the way you do references...in the "new way".
You have the below setup, except for repositories.config and the 3 packages.config
\SolutionFolder\
\SolutionFolder\MySolution.sln
\SolutionFolder\packages\
\SolutionFolder\packages\repositories.config
\SolutionFolder\CSProjectA\
\SolutionFolder\CSProjectA\CSProjectA.csproj
\SolutionFolder\CSProjectA\packages.config
\SolutionFolder\CSProjectB\
\SolutionFolder\CSProjectB\CSProjectB.csproj
\SolutionFolder\CSProjectB\packages.config
\SolutionFolder\CSProjectC\
\SolutionFolder\CSProjectC\CSProjectC.csproj
\SolutionFolder\CSProjectC\packages.config
Each of the packages.config will look like this
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="4.5.11" targetFramework="net45" />
</packages>
repositories.config will look like this
<?xml version="1.0" encoding="utf-8"?>
<repositories>
<repository path="..\CSProjectA\packages.config" />
<repository path="..\CSProjectB\packages.config" />
<repository path="..\CSProjectC\packages.config" />
</repositories>
When you do a nuget restore, the following will be created
\SolutionFolder\packages\Newtonsoft.Json.4.5.11\
\SolutionFolder\packages\Newtonsoft.Json.4.5.11\lib\
\SolutionFolder\packages\Newtonsoft.Json.4.5.11\lib\net40\
\SolutionFolder\packages\Newtonsoft.Json.4.5.11\lib\net40\
\SolutionFolder\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll
\SolutionFolder\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.xml
All your .csproj references (hintpath) will be
..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll
This is what nuget does for you (auto-voodoo-magically), but I'm explaining it here.
This is how you get consistency from your references.
On your local box, you can just do a normal VS "build" or "rebuild".
If you have missing packages, you can fix it (one time) with this command line call:
nuget.exe restore "\SolutionFolder\MySolution.sln"
When you build (on your build server), you will do a:
nuget.exe restore "\SolutionFolder\MySolution.sln"
msbuild.exe "\SolutionFolder\MySolution.sln"
APPEND
Try this:
"%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe" "MySolution.sln" /p:Configuration=Debug;FavoriteFood=Popeyes /l:FileLogger,Microsoft.Build.Engine;logfile=MySolution.Debug.log
"%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe" "MySolution.sln" /p:Configuration=Release;FavoriteFood=Popeyes /l:FileLogger,Microsoft.Build.Engine;logfile=MySolution.Release.log
And view the log to see the source of the Newtonsoft.Json.dll is coming from (that ends up in ProjectA\bin\Debug).
Now that I relook at your comments and OP, you do have a weird problem. I'm wondering if the ProjectA\bin\Debug\Newtonsoft.Json.dll might be coming from an alternate source.
I have the same problem.
Project A (web app) reference project B (PCL), both have the same newtonsoft nuget package, and A has the binding redirect.
Project C (test project) reference project B and E (PCL too), all having the same newtonsoft nuget package.
When i build project A, project A works ok. IF i build (not rebuild) project C, project E is build a,d project B is skipped (alreadu built). BUT project A is affected: something overwrites the newtonsoft json DLL in its bin folder with a CL version. And now project A won't run with this method not found error.
If i manually replace the newtonsoft json dll in project A with the same one that was in the bin folder before building project C, A works again ok !
If i then start debugging project C, no rebuild occurs, but project A stop working !
I suppose something is wrong with the newtonsoft json assembly between the PCL version and the net45 version, and the .NET engine picks the wrong one. I have added the net45 version to the test project, without success.
UPDATE ------------
The only workaround i found, is to separate projects in 2 solutions and open 2 visual studio.
In solution A, i add project A and B.
In solution B, i add project C and its dependancies B and E.
And now all works as expected. Project A can run, and running/compiling project B does not interfere with project A.
Our main site is ASP.net 4.5 and uses Ektron (A .net CMS) I'm attempting to turn it into an MVC4 / Webforms hybrid.
As far as I can tell I have everything MVC4 needs installed correctly but when I try to hit the default Home controller I get the classic
[InvalidOperationException: The view 'Index' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/home/Index.aspx
~/Views/home/Index.ascx
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx
~/Views/home/Index.cshtml
~/Views/home/Index.vbhtml
~/Views/Shared/Index.cshtml
~/Views/Shared/Index.vbhtml]
I installed MVC4 using NuGet and by copying over the default controllers, view and associated App_Start and Global.asax files from a default MVC4 application. I also installed WebAPI which is working fine (so that tells me routing does seems to be working correctly, i.e. I can go to API/Values and get the default values api data back just fine).
The site is installed as a main website, i.e. not as a sub site or sub application.
I initially thought maybe there was an issue with the handlers section as Ektron (our CMS) has a ton of handlers it adds but have torn the web.config apart and can't find any problems in there. I even tried replacing it with the one from the default MVC4 application and got the same error.
Note, I did have to change one section the default web.config and in my custom one.
When I have this section in there:
<dependentAssembly>
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.10.0" newVersion="2.1.10.0" />
</dependentAssembly>
I get the error
Could not load file or assembly 'System.Net.Http, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
I looked at the assembly details for that DLL and found it was version 4.0.0.0 so I changed that section to say
<dependentAssembly>
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
Which fixes that error and as far as I can tell is OK but again, I'm left with the above problem of the views not being found.
Any help would be greatly appreciated.
OK, I feel dumb.
#SLaks simple question helped me find the answer.
We have a rather complicated build system. It combines the Ektron base code project, which is a web site not a project, with our main project and class libraries into output directories, in this case /debug which is where my IIS is pointing. There's several steps involved, including converting our web project back into a web site during "build" (don't ask, it's a pain but speeds up build times a ton).
Anyway, we only copy certain file types out and .cshtml wasn't in the list, so yeah, no view folder in the output debug directory . . .
Tl;dr version: I am stuck with the exception: System.IO.FileLoadException : Could not load file or assembly 'DotNetOpenAuth.AspNet, Version 4.0.0.0 ...
A bit dismayed that msft used so many static classes and methods for auth in the new MVC4 project template. Want to wrap all membership/auth functionality into a class that implements an interface so that I can mock for unit tests.
After a couple of evenings of struggling, I have decided to start from scratch, so I removed all DotNetOpenAuth* assembly references and nuget package.config references. I have similarly removed all references to Micrsoft.Aspnet.WebPages.OAuth.dll.
Reinstalling packages: I run install-package dotnetopenauth.aspnet against three projects in solution which need the dll references.
Solution will not build, as my wrapper has a method which wraps: Microsoft.AspNet.WebPages.OAuth(.dll).OAuthWebSecurity.RegisteredClientData and therefore I need a reference to this assy, so I run install-package microsoft.aspnet.webpages.oauth against the same three projects.
Solution builds, but when I run the unit test referencing Microsoft.AspNet.WebPages.OAuth(.dll).OAuthWebSecurity.RegisteredClientData I get a runtime exception: System.IO.FileLoadException : Could not load file or assembly 'DotNetOpenAuth.AspNet, Version 4.0.0.0 ...
The references to this assembly in all three projects reference 4.1.0.0, as does the DotNetOpenAuth.AspNet assemblyIdentity in my web.config.
I'm using resharper to run the test, and the tests are nunit style.
And finally here is a paste of what I see in fuslogvw. Obviously something is looking for 4.0.0.0 but I can't figure out what or what to do about it (I have a couple of times deleted the temp data folder referenced in this dump):
***** Assembly Binder Log Entry (11/13/2012 # 10:04:54 PM) ************
The operation failed.
Bind result: hr = 0x80131040. No description available.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
Running under executable C:\Program Files (x86)\JetBrains\ReSharper\v7.0\Bin\JetBrains.ReSharper.TaskRunner.CLR4.MSIL.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = i7\dave
LOG: DisplayName = DotNetOpenAuth.AspNet, Version=4.0.0.0, Culture=neutral, PublicKeyToken=2780ccd10d57b246
(Fully-specified)
LOG: Appbase = file:///C:/SVN/trunk/SoAndSo45/SoAndSo.Com.Tests.Unit/bin/Debug
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = C:\Users\dave\AppData\Local\Temp\kpsvgxtp.io4
LOG: AppName = SoAndSo.Com.Tests.Unit
Calling assembly : SoAndSo.Com.Tests.Unit, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: Post-policy reference: DotNetOpenAuth.AspNet, Version=4.0.0.0, Culture=neutral, PublicKeyToken=2780ccd10d57b246
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:///C:/SVN/trunk/SoAndSo45/SoAndSo.Com.Tests.Unit/bin/Debug/DotNetOpenAuth.AspNet.DLL.
LOG: Assembly download was successful. Attempting setup of file: C:\SVN\trunk\SoAndSo45\SoAndSo.Com.Tests.Unit\bin\Debug\DotNetOpenAuth.AspNet.dll
LOG: Entering download cache setup phase.
LOG: Assembly Name is: DotNetOpenAuth.AspNet, Version=4.1.0.0, Culture=neutral, PublicKeyToken=2780ccd10d57b246
WRN: Comparing the assembly name resulted in the mismatch: Minor Version
ERR: The assembly reference did not match the assembly definition found.
ERR: Setup failed with hr = 0x80131040.
ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated.
Thanks!
I think you should be able to install these as NuGet packages into your unit test project and have them work if you include these binding redirects to your test project's app.config file:
<dependentAssembly>
<assemblyIdentity name="DotNetOpenAuth.AspNet" publicKeyToken="2780ccd10d57b246" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="DotNetOpenAuth.Core" publicKeyToken="2780ccd10d57b246" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
</dependentAssembly>
If you have a fresh MVC project and run NuGet's Update-Package command on it, these are automatically created. If you hadn't run that, and installed the NuGet packages fresh into your unit test project, then your unit test project would have references to newer assemblies than your web project did. That would cause the load failure you saw, I think. You just have to make sure that either all your assemblies have common versions across your solution, or that the required binding redirects are in place. And in fact I think the binding redirects are required anyway, since the DotNetOpenAuth assemblies have been updated more recently than the Microsoft.AspNet.WebPages.OAuth package has.
Got some good help from a PM on the ASP.NET team at Msft, who recommended that I copy/reuse the collection of DLLs that are included in the MVC4 project template, which I have done and it's currently working for me.
I copied the DLLs directly to a "non-managed" folder outside of NuGet's purview so that they don't inadvertently get updated unless I really want them to be.
Also worth noting, I had to clean out some references and assy forwarding in web.config to 4.1.0.0, since the MVC4 project template includes 4.0.* of all of the DotNetOpenAuth stuff.
I have updated the Sharp Architecture solution (SharpArchitecture_1.0_RTM_build_486) (my local copy) and referenced NHibernate 2.1.0.4000 instead of NHibernate 2.1.0.3001 dll. I have also updated all other NHibernate related references in Sharp Architecture solution.
I was able to rebuild Sharp Architecture and to pass all the tests using the NHibernate version 2.1.0.4000. I have used the provide build script.
When I update the references (NHibernate and recompiled Sharp dlls) in my application and try to initialize NHibernate, the application is throwing "Could not load file or assembly 'NHibernate, Version=2.1.0.3001, Culture=neutral, PublicKeyToken=aa95f207798dfdb4' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)"
This error is thrown in NHibernateSession.Init method. The calling assembly is SharpArch.Data.
Besides recompiling the Sharp Architecture with new dlls, is there something else that needs to be done? The Sharp Architecture is strongly typed against NHibernate 2.1.0.3001.
The reason why I'm doing this is because I want to include NHibernate.Cache in my application. The NHibernate.Cache is compiled against NHibernate 2.1.0.4000 (NHibernate-2.1.0.GA-bin)
Add the following within your web.config file before the opening of the system-web tag.
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="NHibernate" publicKeyToken="AA95F207798DFDB4" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-2.1.0.3001" newVersion="2.1.0.4000"/>
</dependentAssembly>
</runtime>
This should solve the problem.
A similar question has been asked in the s# group and and by Tom Cabanski
There are name changes that need to be made in both the original S#-Arch source, so you'd need to re-build that too (not just your own solution derived built on the framework).
As of writing these changes are not yet in the trunk so might be worth waiting unless you're really desperate?
Try to find and delete all 2.1.0.3001 versions of the DLL from your PC (including versions of the DLL in the GAC) and then recompile / rerun. Hopefully you'll get an error from whatever was trying to reference that version of the DLL and you can update that reference to use the newer 2.1.0.400 version of the DLL.
newVersion="2.1.0.4000" should be newVersion="2.1.1.4000"
I want to work with a DataGrid in Kaxaml. How do I reference the toolkit dll?
Copy WPFToolkit.dll to "C:\Program Files\Kaxaml\"
Restart Kaxaml
Now you can use such namespace:
xmlns:dg="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit"
Another option would be to make a junction and add a probing path to Kaxaml's config.
Make Junction to code
run elevated cmd
cd "c:\Program Files (x86)\Kaxaml"
mklink /J ProbeFolder "c:\path-to-your-code"
Modify Kaxaml.exe.config
run elevated notepad
open "C:\Program Files (x86)\Kaxaml\Kaxaml.exe.config"
add the following to the <configuration>:
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="ProbeFolder"/>
</assemblyBinding>
</runtime>
save the file
restart kaxaml
When mapping custom classes and namespaces in XAML using the clr-namespace/assembly notation, you can't specify the path of the assembly containing the class but just the assembly's name (more details can be found on MSDN), since all referenced assemblies must be linked during the XAML compilation via the project file.
Kaxaml doesn't support the concept of a project since it doesn't do any compilation but rather dynamically parses and renders the XAML entered in the editor "on-the-fly" by using the System.Windows.Markup.XamlReader class.
This means that when using Kaxaml you can only reference classes contained in the assemblies that are part of the .NET Framework.
Building on top of Todd White's solution (& this is future reference for myself too) your XAML in Kaxaml would reference a 3rd party library as follows:
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:dxlc="clr-namespace:DevExpress.Xpf.LayoutControl;assembly=DevExpress.Xpf.LayoutControl.v13.2"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Layout Control Start -->
<dxlc:LayoutControl Orientation="Horizontal">
</dxlc:LayoutControl>
<!-- Layout Control End -->
</UserControl>