Compile .net 4.0 project on build server with .net 4.5 - .net-4.0

We're having the seemingly common error
Could not load type 'System.Runtime.CompilerServices.ExtensionAttribute' from assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
in a project that needs to be compiled against .Net 4.0 but is built on a build server running Windows Server 2012 (with .Net 4.5). The project is a web application that gets deployed to a web server running 2003, where installing .Net 4.5 isn't an option. There it runs against "classic" .Net 4.0
From similar questions, we're trying command-line options to MSBuild:
/property:FrameworkPathOverride="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0"
We also tried various combinations of
/property:ReferencePath="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0"
/property:NoStdLib=true
/property:NoCompilerStandardLib=true
The reference assemblies (including the .dll files) are in fact installed in that place on the build server. But when we deploy the website and visit the home page, we get that error. (Interestingly, on a page reload, the error disappears, and the site operates normally.) What are the MSBuild parameters necessary to compile against the .Net 4.0 assemblies?
Update
I turned on ludicrous-level logging on MSBuild, and I see that apparently it is building against the .Net 4.0 reference assemblies:
Resolved file path is "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll
and I didn't see any mention of assemblies outside that folder or the build server's working directory. So it appears to compile properly, but when deployed on the web server, it throws the exception.
As to the exception going away on a page reload, I wonder if that's related to the markup pre-compile step. We're running aspnet_compile on the build server. Maybe if there's an exception coming from a generated assembly, the web server will re-compile it. And the recompiled assembly is fine, because it was created with true .Net 4.0.

Well the answer turned out to be borderline embarrassing. After we confirmed from detailed MSBuild output that it was in fact building the website project against the right reference assemblies, we realized that there are several in-house NuGet packages in the project that had been built against .Net 4.5. One of them was chock full of extension methods, which is what causes the exception. Rebuilding them against .Net 4.0 fixed the problem.
Which brings up an interesting issue. If a 3rd-party NuGet package is compiled for 4.0 but using 4.5 references, we'd be in the same situation, but not able to fix it. So the lesson for package publishers is to ensure your 4.0 version is compiled against the reference assemblies.

Related

.Net Framework 4.7 console app references .NET core dll - unexpected files in output directory

I have a .NET Framework Console app (.Net Framework 4.7) which references a .NET Core dll (.Net Standard 2.0). The .Net core dll uses nothing outside NETStandard.Library.
I noticed some unexpected files in the /bin/Debug directory. After some investigation I have determined that these are not coming from any of the referenced packages, but are being copied from
C:\Program Files (x86)\Microsoft Visual Studio\Preview\Community\MSBuild\Microsoft\Microsoft.NET.Build.Extensions\\net461\ref
The contents of this directory differ across the machines we are using, causing different DLLs to end up in the output directory. This was making the debugging process inconsistent.
Now that I have worked out what was causing the problem, I was wondering what the explanation of this is, and whether there is a way to prevent it from happening, ie to have only the packages referenced in the project be copied to /bin/Debug
These files are expected and even required to allow .NET Standard libraries to work on .NET Framework. They contain the necessary type forwarding definitions so that at runtime, every assembly can be loaded correctly - for example, libraries can reference System.Object from netstandard.dll (.NET Standard >= 2.0) or System.Runtime.dll (.NET Standard < 2.0). The additional assemblies in your output file will redirect the type to .NET Framework's mscorlib.dll.
There is this GitHub issue answering a similar question.
Note that the upcoming .NET Framework 4.7.1 will have the all the required type definitions and forwards out of the box so once a project targets 4.7.1, no additional assemblies will be added to your project's output folder.

Could not load file or assembly 'System.Web.Http.WebHost, Version=4.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35'

In Visual Studio 2012 I created an ASP.NET MVC 4 project where the target framework is the .NET Framework 4.5. When I deployed my project to a web server it gave the following error:
Could not load file or assembly 'System.Web.Http.WebHost, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file
specified.
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.IO.FileNotFoundException: Could not load file or
assembly 'System.Web.Http.WebHost, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35' or one of its dependencies.
The system cannot find the file specified.
Source Error:
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.34237
I had the same issue today during deployment. I was able to fix it by marking the assembly to be copied to the deployment file.
In order to do this, in my Visual Studio project, select the System.Web.Http.Webhost assembly in your references and alter the 'Copy Local' property to True. I had to repeat this for a few other assemblies that were missing.
Thanks to this website for the tips - http://haacked.com/archive/2008/11/03/bin-deploy-aspnetmvc.aspx/
Check the bin folder of your deployed project. It should contain System.Web.Http.WebHost.dll.
If this dll is in this folder, check it version. If it isn't 4.0.0.0, then you should deploy version 4.0.0.0 or change your web config to use other version (not really good idea because of dependencies)
Try to reinstall Microsoft.AspNet.WebApi package. Open Package Manager Console and type:
Update-Package Microsoft.AspNet.WebApi -reinstall
Be careful, this command will remove all dependencies and you will have to install them manually.
I had this error with an old project that I was going back to do a bit of work on. It turns out the project wasn't actually using WebApi so I uninstalled Microsoft.AspNet.WebApi using NuGet. That solved the problem for me.
If I'd actually have needed WebApi I'm sure installing it again would have fixed the error too.
I ran into this today after setting up a new Team City Build Agent. The new agent didn't have MVC 4 installed, perhaps part of the problem. Fortunately, I found this article which lead me to the solution. In Team City, I just updated the Build Step for the Nuget Restore so that it doesn't use the local cache.
This works because the cache may have been established by build runners with different (MVC) frameworks installed already.
I know this is answered but I thought I'd add something.
Every time I set "copy local" to true on a file causing the error I'd publish it and just get another one. So I just selected all of the files under references and set them all to true. This fixed the issue for me.
Important: This error message can be caused because you are deploying a 4.5 project to a server that doesn't have 4.0 installed. Make sure you have the .NET Framework version installed in IIS for the project you need. Some of these DLLs by default won't copy up, because it uses the core project DLL normally. Check to make sure your production server has the .NET version you're going with. I experienced this myself with a 4.5 project on a 4.0 server.
Ensure ASP.NET MVC 4 is installed on your server. Check it in the following location -
C:\Program Files (x86)\Microsoft ASP.NET\ASP.NET MVC 4

Missing GAC with .NET Framework 4 Installation

I've installed the full version of .NET Framework 4 (Client Profile + Extended) on a customer machine which is running Windows Small Business Server 2003 Standard Edition. The installation was successful without any errors. There were no errors mentioned in the log files either...
BUT the .NET Framework 4 GAC (Global Assembly Cache) is completely missing! In other words, the following folder is missing:-
C:\Windows\Microsoft.NET\assembly
If I look into the C:\Windows\Microsoft.NET folder, I can only see 2 subfolders (as shown below) and nothing else.
authman
Framework
The server still has .NET Framework 3.5 installed and is running properly. This means that the GAC folder below exists and has all .NET library DLLs in it. But of course, there are no .NET 4 DLLs in there.
C:\Windows\assembly
Because of the missing .NET Framework 4 GAC, none of my applications run. They all complain about missing System or System.Xml references. If I copy the missing files from the C:\Windows\Microsoft.NET\Framework\v4.0.30319 folder to my application directory, they will stop complaining about these files and start complaining about other missing .NET files. Obviously I use a lot of .NET Library references, and I don't want to copy the whole .NET Framework folder into each of my applications.
Does anyone know how to create the missing GAC? Or at least find out what causes the GAC to disappear? I tried multiple times to re-install the .NET Framework 4, but the GAC is always missing...
Edit: I've also tried running gacutil.exe -l to see what is in the GAC, it only list out .NET assemblies of version 1.0 to 3.5. All .NET 4 assemblies are missing.
Note: .NET 4 version of gacutil.exe only comes with Visual Studio (or Windows SDK), so I have to copy the file to the customer site.

Why can't MSBuild ToolsVersion 4.0 build older projects?

We're using Cruse Control to manage our build process.
AS we convert vs2008 projects to vs2010, we're leaving the target framework set at 3.5 for web and class library projects.
At this point we're not going through and converting all our solutions to vs2010; not if we don't have to.
I recently updated the MSbuild project files that cruise control uses to point at MSBuild 4.0 so our build process would be able to build vs2010 projects.
C:\windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe
All was well until a web project that was targeting the 4.0 framework was committed.
At which point this error popped up:
CS0433: The type 'System.Web.Routing.RouteCollection' exists in both c:\Windows\Microsoft.NET\assembly\GAC_32\System.Web\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Web.dll and c:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Web.Routing.dll in Global.asax.cs(15, 43)
At which point I became aware of the Windows/Microsoft.NET/Assembly folders.
Now... All the MSBuild projects, even though they were using MSBuild 4.0, still had the tools version set at 3.5.
So why was a 3.5 targeted build looking at the new 4.0 assembly folders and finding this conflict? Probably because I was using MSBuild 4.0. But if I can change the toolVersion that MSBuild uses, you'd think I can tell it to target 3.5 without worrying about these potential conflicts.
To resolve this issue, I went to the relevant MSBuild project files that cruise control uses and changed their toolsVersion to 4.0. This got passed that conflict error. But now everytime it tries to build a project that's in a solution that we haven't yet converted to a vs2010 project, it breaks with an error like this:
MyProject.csproj in SomeFilePath:
LC0000: 'Could not load file or assembly or one of its dependencies. This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded.' in LC(0, 0)
If I open the solution that contains that project in Visual Studio 2010 and do the conversion, build it and commit that and force another build, I get passed that error only to find that another not yet converted project is tossing that same error.
So now I am for sure using MSBuild 4.0 and for real targeting the 4.0 framework. Why can't 4.0 build 3.5 projects or vs2008 solution projects?
The issue is that you have migrated part of your projects to to visual studio 2010. Any 2008 project that references a 2010 project (by project reference) will give you this compile time error. Try updating all .csproj files to 2010 and try rebuilding again.

Where is the .NET Framework Global Assembly Cache?

I installed the VS2010 and .NET 4.0, then I compiled an assembly and ran the gacutil using the exe available on
%ProgramFiles%\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools
The output of the executable said the assembly was sucessfully installed on Global Assembly Cache. However, when I go to %WINDIR%\assembly folder I cannot find the assembly I installed using the .NET Framework 4.0 gacutil.
I've seen some posts saying the .NET Framework 4.0 has a separated GAC, but what I haven't found was where it is located.
May someone to help me to check where can I see the Global Assembly Cache of .NET Framework, as it used to work on previous version (%WINDIR%\assembly)?
Yes, there are two distinct GACs as from .NET 4.0
See here: .NET 4.0 has a new GAC, why?
As stated below, the new physical location is %windir%\Microsoft.NET\assembly\ (you can interogate it using the dir command at a command prompt if you're interested).
It's worth noting that applications running up to the 2.0 CLR will not even be able to see assemblies in the new GAC.
Try:
%windir%\Microsoft.NET\assembly\
Due to Common Language Runtime (CLR) changes, the contents of the Global Assembly Cache (GAC) is split between two directories:
%WINDIR%\assembly\
%WINDIR%\Microsoft.NET\assembly\
If you run the command gacutil -l from the directory of your project's .csproj file, you will get a printout of the contents of the GAC (the contents of both directories).