I have a reference to these assemblies in my MVC project
Microsoft.ReportViewer.WebForms
Microsoft.ReportViewer.Common
Version is 11.0 but I set it to SpecificVersion = False and CopyLocal = False
But upon deploying, I keep getting this error:
Could not load file or assembly 'Microsoft.ReportViewer.WebForms, Version=11.0.0.0,
The available versions in GAC are 10.0 and 12.0 but I thought it should simply load whatever is this (hopefully 12.0 since it's the latest one) since I set CopyLocal to false. What am I doing wrong here? Is there a best practice for this since we don't really know what version will the clients have in their GAC but we want to support both versions.
SpecificVersion = False is only a hint for the compiler. Once compiled, your project is bound to a specific version of that assembly.
Since different assembly versions could have differences that are not compatible with each other, it is not safe to just pick any available version.
Solutions:
Support just one ReportViewer version
Have different projects for different ReportViewer versions
Use reflection
Use binding redirects
Related
I'm using tlbimp to generate a .Net interop of a COM assembly. This COM assembly has a product version and file version like 7.X.X.X but when I'm using TlbImp, my interop has then a version like 1.Y.0.0. I'm aware I can change this version when I'm using TLBImp via parameters of the executed command lines but I'm wondering where this version comes from.
Can I access a manifest of this COM assembly?
Why I cannot see this version on the property of the file in the explorer?
I have different version of this assembly and I see the version generated always different but I'm failing to find where this version come from.
Thanks
I had a hunch that it was the version of the typelib. I took a test project that had a typelib of version 1.0 and ran tlbimp on it, and it produced an import assembly with file version of 1.0. I then changed the version of the typelib to 1.19, recompiled, and reran tlbimp. The file version of the new import assembly was 1.19 (well, 1.19.0.0).
Using OleView you can load the typelib of the EXE/DLL your using for tlbimp. Check the version of the typelibrary. Compare it to the file version of your import assembly. I bet they match.
Makes sense they'd want the version numbers to match.
I found some interesting articles about the difficulties of .NET Core SDK/runtime/tooling versioning, for example:
.NET Core Versioning
.NET Core versioning
Supporting both LTS and Current releases for ASP.NET Core
However I still don't really know how to deal with all of this in practice:
Given a project with a number of .Net Core dependencies. How can I determine which version of the runtime needs to be available on the end-users machine?
Does the runtime version need to match exactly, or can the runtime installed on the end-users machine be newer than the required version?
Let's say I want to stick to some LTS version of the runtime. How can I determine the version of the packages I need to reference? How can I make sure that no newer packages are referenced?
Oh, and there is one more:
Once I know which runtime version is required on the end-users machine, how can I determine (programmatically) if that version of the runtime (or a newer, backwards compatible one) is available?
First, let's look at what happens when a portable .NET Core application is run via dotnet yourapp.dll:
The muxer executable (dotnet.exeon windows) loads a version of the host framework resolver (hostfxr) from a folder beneath host\fxr\ next to dotnet.exe.
The host framework resolver looks at yourapp.runtimeconfig.json (or a different file if configured when using dotnet exec) to find out which framework you are targeting. This extracts a framework name (Microsoft.NETCore.App) and a version (e.g. 1.1.0).
It then looks inside the shared\Microsoft.NETCore.App folder (based on the framework name) for available versions.
Based on the available versions and the framework version from yourapp.runtimeconfig.json it determines which version to use. Or it may decide to error out and complain that the required version is not available.
👆 this is the hard and sometimes confusing part.
Currently (.NET Core 1.0), the framework resolver will use the latest patch version available for the major and minor version specified in the runtimeconfig.json but no version lower than the runtimeconfig.json specifies. E.g. a 1.1.2 runtime will be used if the runtime config specifies 1.1.1, but if on only 1.1.0 is available, it will log an error. There is also no version roll-forward across minor versions. So an app with a runtime config set to 1.0.0 will trigger an error if only any 1.1.* is installed.
For .NET Core 2.0, a minor version roll-forward is planned in case no matching minor version is found - if a 1.0.5 and 1.1.2 runtime are installed, an app with runtime config of 1.0.4 will be run on the 1.0.5 runtime. If only 1.1.2 is installed, the same app will be run on 1.1.2. If only 2.0.0 is installed, the same app will not be able to run. See GitHub issue for .NET Core 2+ Version Binding for details and discussion about this change.
Let's look at where the value in the runtime config comes from. When you target the framework netcoreapp1.1, the tooling you use will determine:
Which NuGet package (+ version) to use so you get the compilation references to be able to compile.
Which version to write into the yourapp.runtimeconfig.json
In the csproj file, the version of the framework to use is determined by the property
<RuntimeFrameworkVersion>1.1.2</RuntimeFrameworkVersion>
If this value is not specified, the tooling will use the newest version it knows about
for .NET Core 1.0 and 1.1.
For .NET Core 2.0, portable applications will use the patch version 0 by default and self-contained applications will use the latest version that the tooling knows about. This change is being made because tooling (CLI "SDK" / Visual Studio) updates and runtime updates have been released at the same time so apps would require the new runtime to be installed on target systems by default. If that runtime was not installed, an error would occur. This was bad if it takes a few days for hosters to catch up with testing and installing updates. The version can still be enforced / required by setting <RuntimeFrameworkVersion>explicitly.
About packages: The packages that 1.* tooling uses are meta-packages. So referencing Microsoft.NETCore.App or NETStandard.Library would pull in a lot of other NuGet packages. This is no longer the case for .NET Core 2.0 and .NET Standard 2.0 - the packages are flat and contain everything you need. Also, when you create a NuGet package, those packages will no longer be dependencies of the resulting package. They are used for compilation references only, with the exception of Microsoft.NETCore.App knowing which additional packages to pull in for self-contained applications.
Previously, a library built with NETStandard.Library version 1.6.1 would cause consuming .NET Core 1.0 applications to contain a lot of updated DLL files that are actually part of .NET Core 1.1. I do not know if this means that LTS policies will cover or not cover applications that end up with those DLLs. And it is hard to see which .NET Core version they belong to since the package versions they originate from are usually 4.0.*, 4.1.* and 4.3.*.
For ASP.NET Core packages, it is a lot easier since they are versioned 1.0.* and 1.1.* so you can see which "branch" they originate from and you have more control over the versions used by specifying the NuGet packages in the csproj file.
To recap, let's get back to the original questions:
Given a project with a number of .Net Core dependencies. How can I determine which version of the runtime needs to be available on the
end-users machine?
The real dependency here is which version of Microsoft.NETCore.App is written to the yourapp.runtimeconfig.json file. A version of the same major and minor number and same or higher patch number has to be installed, the latest patch version will be used. When the .NET Core 2.0 resolver is installed, alternatively the highest version with the same major number will be used instead, but a version of the same major and minor number will be preferred.
If only runtimes with newer major versions are installed, the app cannot be run on the target system. (e.g. 1.0.5 app and only 2.0.0 runtime)
Does the runtime version need to match exactly, or can the runtime installed on the end-users machine be newer than the required version?
The version of the runtime config is a hard minimum. For choosing the right version of newer runtimes see above.
Let's say I want to stick to some LTS version of the runtime. How can I determine the version of the packages I need to reference? How
can I make sure that no newer packages are referenced?
The version of Microsoft.NETCore.App will automatically be inferred from the target framework (e.g. netcoreapp1.0 => 1.0.*, patch version depending on the version of the tooling you use). To override the version, set the <RuntimeFrameworkVersion> property as discussed above.
If new NuGet packages are referenced transitively, e.g. by consuming Newtonsoft.Json 10.0.0 from a .NET Core 1.0 app (see GitHub issue), some extra DLLs might be added to the project's output. These are newer versions of DLLs that are part of the runtime, but override the versions from the runtime.
If you really want to make sure that you don't use any FTS versions, you'd need to explicitly reference all these packages in your csproj file so NuGet will downgrade the version of the packages used (and emit package downgrade warnings).
The problem here is that there hasn't been a case where an issue has not been fixed in 1.0 and 1.1 packages. If this will be an issue in the future when 1.0 and 2.0 are supported but 1.1 no longer, we will have to see how this will be handled case by case. (though there certainly be pressure/requests from the community to release updated 1.1 versions as well even if not covered by Microsoft's support).
If you use a 2.0 or higher version, those implementation packages will be trimmed out of the dependency graph of your app and no longer be considered when deploying. This happens as part of the conflict resolution logic that knows that the new flat package contains the same DLL files as the individual packages.
Once I know which runtime version is required on the end-users machine, how can I determine (programmatically) if that version of the
runtime (or a newer, backwards compatible one) is available?
Scan the shared\Microsoft.NETCore.App subfolders next to dotnet.exe and implement the same logic used by the host.
PInvoke into the native code of latest hostfxr.dll in host\fxr next to dotnet.exe. But this is fairly complicated to do.
After allowing Nuget to update ImageResizer 3.1.5 to version 3.2.1 my compiles are failing with multiple errors (all same type):
Error 5 Missing compiler required member 'System.Runtime.CompilerServices.ExtensionAttribute..ctor'
Apparently this is the result of an assembly version mismatch. Deleting all ImageResizer references in the project allows an error-free compile.
Reverting to ImageResizer 3.1.5 also allows a successful compilation.
My project is a simple MVC3 application targeting .NET4 - both ImageResizer 3.1.5 and 3.2.1 are targeting v2.0.50727
Any ideas on how this could be fixed?
Thanks in anticipation!
Update (Jun 20th 2012): The best solution is for the project to roll back extension method support. ImageResizer 3.2.2 will no longer offer extension methods, but some of the functionality will be duplicated in the ResizeSettings and Instructions classes to minimize breakage for those who have already coded against the new alpha APIs.
ImageResizer V4 will most likely require .NET 3.5, and will re-introduce the missing features.
Update: please see this question instead if you have any solutions to this catch-22.
I apologize for the issues.
I'm still trying to gather data and discover a long-term solution, but this is what I have so far:
Workaround A:
In Solution Explorer, expand the References folder in your project, select ImageResizer, and go to Properties. Change the Aliases field from 'global' to 'ir'.
Workaround B:
Set your project to use .NET 2.0, save, then revert it back to using .NET 3.5 or .NET 4.
Workaround C:
Manually remove your System.Core reference and add the correct one back. (The usual culprit is an upgraded project with a System.Core 3.0 reference in a 3.5 project). On ASP.NET, you can do this in web.config.
Workaround D:
Revert to 3.2.0, but only if you're using C#.
Why this is happening
VisualStudio/MSBuild find multiple definitions of System.Runtime.CompilerServices.ExtensionAttribute in the project during compilation, but instead of picking the public copy defined in System.Core, the compiler decides to use the internal, assembly-local copy defined in ImageResizer.dll. Then it complains because other assemblies can't reach it. Inane.
What should happen
Microsoft has used this technique several times in the past without issues, and it's widely documented. The compiler is supposed to pick the public instance for project-wide use, but instead it's picking the 'internal' copy. And this isn't affecting many developers; and only a few can reproduce it with a new project.
Public vs. Internal
V2.3.0 defined ExtensionAttribute as public instead of internal. This caused a compile-timer error in VB projects, but not in C# projects. I immediately released 2.3.1 with it marked internal, but I'm now seeing problems with C# projects instead. Catch-22 here.
It works for other people... and Microsoft! Why me?
http://www.danielmoth.com/Blog/Using-Extension-Methods-In-Fx-20-Projects.aspx
http://www.codethinked.com/using-extension-methods-in-net-20
http://kohari.org/2008/04/04/extension-methods-in-net-20/
Using extension methods in .NET 2.0?
The 'hack' was even featured in MSDN magazine.
How you can help
I need more data to completely figure this out. If you're experiencing the issue, please e-mail a .zip file of the project to support#imageresizing.net, and include your VisualStudio/.NET version numbers (Go to Visual Studio, Help, About, and click Copy Info, then paste it into the e-mail).
Hopefully I'll be able to find the exact circumstance(s) that trigger the problem.
Update - just found this article which implies the only solution is creating multiple versions of the assembly. But Microsoft didn't! What am I missing? Also, NuGet doesn't support 2.0 vs 3.5 versioning, so unless I can find a single-assembly solution I might have to drop 2.0 support.
I've installed mono 2.10 along with monodevelop and have used monodelveop to code some apps under ubuntu. Several of these apps needed to access to the JavaScriptSerializer, which is part of the System.Web.Script.Serialization namespace.
In order to be able to instantiate and use a JavaScriptSerializer, I had to add a reference to my app in monodevelop - but I see there appear to be two packages that I can chose from: one named "system.web.extensions" and the other named "mono".
If I use the first package (system.web.extensions) I get a runtime error when using the JavaSerializer. I tried using the "mono" reference instead and it works fine.
So far so good. But now, I want to run this same app under windows and I'm getting a "cannot load assembly" error for System.Web.Exceptions.
I'm confused at this point: Why are there two packages shipped with mono/monodevelop for some of these assemblies, and which one(s) should I be using in order to be cross-platform?
Thanks!
Michael
Why are there two packages shipped with mono/monodevelop for some of
these assemblies?
Mono assemblies are kinds of internal assemblies: they provide additional features, not included in the .NET Framework. The System assemblies rely sometimes on these (i.e. Mono.Web for ASP.NET Web services).
Which one(s) should I be using in order to be cross-platform?
Always use the System ones. The Mono assemblies are not available under .NET Framework (unless you ship them manually).
Mono 2.10 provides two versions of the System.Web.Extensions assembly: 1.0.61025.0 and 4.0.0.0. Be sure to use the 4.0 version.
If the problem persists, could you post your code? (for me, no problem using the JavaScriptSerializer)
Is this the location of the GAC?
C:\Windows\Microsoft.NET\assembly\GAC_MSIL
If so, then what is C:\Windows\assembly?
The answer depends on the version of the .NET Framework being used. Multiple versions can be installed side by side (which is probably the case for you), and programs written for an older version use that version if it's installed.
Before 4.0
All versions before 4.0 use %WINDIR%\assembly (in your case, C:\Windows\assembly) for the GAC. This directory uses a special Explorer view (the Assembly Cache Viewer) to view and manage the GAC.
Since 4.0
Versions since 4.0 use %WINDIR%\Microsoft.NET\assembly (in your case, C:\Windows\Microsoft.NET\assembly) for the GAC. Since 4.0, the Assembly Cache Viewer is obsolete. Explorer displays the GAC directory just like a regular directory.