Hopefully you ASP.NET pros out there can answer this question. I have a single web application that contains a website and a web service - both have several assembly references in common (data access layer, utilities, etc) - however, recent changes made to the web service will require different versions of the common assemblies, versions that the website won't work with (in case you're wondering, the website is some legacy 1.x .NET code that explodes when using the newer version assemblies.)
Can anyone think of a way to allow my web service to reference one version and have my website reference another? I can obviously have only one version with the same name within the bin folder.
Thanks!
(P.S. - It just dawned on me that I could probably compile and reference the common assemblies with a different name, and place those in the web app's bin folder - but that sounds really fugly...)
Or you could separate the webservice into a new application independant of the website.
You can use the runtime part of the web.config to specify the dll to use (We have done it for SQLLite before):
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<qualifyAssembly partialName="System.Data.SQLite" fullName="System.Data.SQLite, Version=1.0.60.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139" />
</assemblyBinding>
</runtime>
I have a single web application that contains a website and a web service
That's your main problem there, you've released a partially functioning Application that relies on two different library code bases...
Even if you were to duplicate and re-reference your common assembly with a different name, you're still boned (pardon the phrase) re: Namespaces of all your classes inside that assembly.
I think you're best bet, would be to Pull the webservice out of your Web Application temporarily, and host them as two seperate app's until you can get your Common Lib's versioning issues sorted out.
I don't think compiling the newer set into an assmebly with a different name would work - .NET would still see the same namespace - so at best you'd have "Ambiguous Reference" or "Type x is already declared in dll y" errors, or at worst the framework would load the one relevant to the part of the app that was called first (website => 1.1, webservice => 2.0) and ignore the other one.
Your best bet would be to refactor the application in to two - web site and web service.
We've been doing this over the last couple of years with one of our clients - they have a huge site built on ASP.NET 1.1, but recent stand alone projects for them have started to move to 2.0 (3.5 under the hood, but obviously that's still hosted under 2.0) - we've basically had to port the common code to a new set of libraries built against 3.5, taking advantage of the new language features as we go, and we've moved those sections to new web sites (in IIS) as they are completed.
It's not ideal, yes we're then left with two copies of the codebase (1.1 and 2.0) and any fixes generally have to be rolled out in two places, but it seemed the best way to start moving them on.
Related
I have been working on a library which can perform various email actions with either EWS or MS Graph.
I had great success implementing EWS because of the limited amount of dependencies required for the EWS API. However when I implemented MS Graph into the library the amount of external dependencies grew ALOT, I went from (estimated) 2-3 external dependencies to 15-17.
(By external dependencies I am refering to dependencies which does not come standard with .Net framework 4.8)
All these depedencies are installed with the nuget package manager.
While I only had EWS implemented I had no issues to get ILMerge to merge the final DLL with the external dependencies, but as soon as I implemented Graph ILMerge would no longer work.
This is a problem as the library was originally developed for use in an application called Kofax TotalAgility (KTA), but this application would only store the single DLL as a blob in its internal database. This meant that when KTA read the dll for classes and methods (KTA gives an overview of available methods to be executed along with input and return parameters) the application would fail telling me that it could not resolve "Azure.Identity.dll".
After SO MUCH STRUGGELING to get ILMerge to work, but with no luck, I yielded and tried another approach.
I decided to develop an ASP.net Core application which would expose the methods in the DLL as a REST service, this in theory was an okay solution as KTA has excellent REST service support.
This new REST service worked on the premise that controllers would have post mappings for each method, and the controller would call my library.
Having the library external would be preferred as I might need it as standalone later.
Now having developed the REST API I created some Unit tests to test the different endpoints, to make sure everything worked as it should.
These told me that the EWS implementation still works as intended, but the Graph implentation throws an error: System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Identity.Client, Version=4.39.0.0, Culture=neutral, PublicKeyToken=0a613f4dd989e8ae'. The system cannot find the file specified. File name: 'Microsoft.Identity.Client, Version=4.39.0.0, Culture=neutral, PublicKeyToken=0a613f4dd989e8ae'
I held my hopes high as the missing dependency was no longer the "Azure.Identity.dll", hoping that copying the missing DLLs to the IIS Application folder (next to the executable) would fix the issue, this however did not help anything.
I have since not been able to find any other solution.
I have thought about an internal assembly resolver which would be a C# event run everytime a dependency should be resolved. I would subscribe to this event in the class contructor, so that it would be ready whenever a method was called.
This probably would fix the issue in ASP.net Core, but it would not be fixed in KTA. If KTA should load classes and methods then the library is never "instantiated", I have tried doing the assembly resolve solution using a static constructor, but this does not help.
To sum up here is a list of things I have tried:
AssemblyResolver in a static contructor
RegAsm all the depedencies needed
Putting all depedencies next to the executable
Uploading all the dependencies to KTA Store
Merging all dependencies using ILMerge and ILMergeGUI
Embedding interop types (long shot, but I am desperate)
Trying to merge only dependencies that could not be resolved
Copying gacutil from my development machine to the target machine to use that instead of RegAsm (also a long shot)
Loading depedencies directly as an embedded resource
The optimal solution I am looking for is a library that is free of external dependencies.
But I can settle for a solution to my dependency problem in ASP.net.
I hope you can help.
I am facing the issue of "Out Of Memory Exception" coming from NRecoPdfRenderer on my ASP.Net application (not using Mvc application).
NRecor PdfRenderer web .Net Component web site
This causes my web site to stop responding. When I remove the NReco.PdfRenderer.dll from project all works fine. Can any one tell me what is going on?
Could you clarify when 'OutOfMemoryException' occurs - when you call NReco.PdfRenderer API or when you just add a reference to the nuget package (or DLL) to your project and that's all?
In the last case I may assume that your project has another 3rd party library that scans all project assemblies (with a reflection). NReco.PdfRenderer.DLL is obfuscated and this may cause 'OutOfMemoryException' when its assembly is analyzed with a reflection; to fix this only way is usage of un-obfuscated build, it may be provided upon request.
I am getting the following runtime exception, except I think my case is different than the dozen or so I've seen so far, most of which are a couple years old.
Could not load file or assembly 'System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The system cannot find the file specified.
We had been using System.ValueTuple and ran into these common issues back when they first incorporated the library into the core language. Since then we have removed all references to the old nuget package and all projects target 4.7.
Since then we have been successfully using the ValueTuple constructs throughout our solution without any problems. Until now, I have a specific call that fails, while other calls that return a ValueTuple succeed, from within the same method. I don't know what the difference could be since all the calls use custom objects serialized across a SignalR hub through an interface like:
Task<(MyObject myobj, Guid myguid)> GetStuffd(Guid id);
I bumped all our projects to 4.7.2. I removed every binding redirect in every app.config file. Still nothing. And since other ValueTuple calls work from the same project, I don't think I'm on the right track with these kinds of solutions. Any ideas?
The problem was actually server-side and removing the binding redirect from my host service easily solved the problem.
It's worth noting that a new .Net Standard 2.0 library was the catalyst here. My call down into a .Net Standard class library is what prompted the issue. This is what was different from other calls already using ValueTuple.
Clearing the binding redirects was indeed the solution after all.
I am looking for a possible solution where I can add ShapeMap.dll as a reference,
but when I try to add the reference I get an error stating:
You can't add reference to ShapeMap.dll, as it was not build against the Silverlight runtime. Silverlight projects will only work with Silverlight Assemblies"
What do I do now?
While Silverlight code may look and smell like good old .NET-backed logic, the runtime for Silverlight is different from that supporting regular .NET applications.
It is useful to think of the Silverlight runtime as a subset of the .NET runtime: Silverlight is meant to run in a "sandbox" whereby many the unsafe features such as direct access to the file system are not allowed.
For this reason, one can only add Silverlight assemblies to a Silverlight project.
The error you're getting is therefore as said: the version of ShapeMap.dll you have wasn't build for Silverlight runtime.
There are two ways out of this situation:
find or build a Silverlight-backed version of the DLL
somehow refactor the Silverlight application so that it leverages the features of the DLL by way of WebServices (if that makes sense, for the name ShapeMap.dll indicates that this may deal with UI objects which are hard/impossible to deal with remotely)
To get a Silverlight-backed version of the DLL:
First choice: It may just be that you can get the binary of the Silverlight version of the assembly where you found the .NET version.
Second choice: it may be that you can get the the source code of the [.NET targeting] DLL.
If so you can try -and I stress "TRY"- to make a Silverlight assembly out of it. The problem may be that the source code uses .NET-only idioms/API calls and you'll then need to convert these; several just .NET-to-SL "gotchas" can easily be converted, others are absolute roadblocks (eg. direct access to the file system, registry etc.), although, it may be possible to merely comment-out the offending sections of the code, if, somehow the Silverlight was not going to use the underlying features of the DLL.
Now... for sake of full disclosure...
there are a few techniques which allow "fooling" Visual Studio so that .NET assembly be accepted within a SilverLight project. See for example "Reusing .NET assemblies in Silverlight". Beware, however, that while very insightful as to the nature of the .NET and Silverlight runtimes, and possibly useful in some cases, these techniques are undocumented and, more importantly, depending on the subset of .NET API used by the DLL, may merely allow to get over over the build-time blocking, to fall into various run-time errors (when/if the application makes calls into the DLL to methods which in turn invoke .NET-only methods of the runtime).
If you have access to the source files for that assembly (dll), create a new Silverlight Class Library project and add all the existing source files to your new project. Then attempt to build the project. Depending on the amount of dependencies you may succeed in building a silverlight compatible version of the assembly.
If you don't have the source code, then sorry you're out of luck.
Silverlight works in a "subset" of the .net framework, some stuff is organized differently and works not like a regular WPF application (like that everything needs to be async in order to keep the UI responsive). You can see it as a "protected" .net environment, and therefor you may not reference or use non-silverlight dll's.
Like the previous answer states, use the source code and copy paste it into a SL library project, compile, and use that.
I have a library that is meant to be used by many websites. The way I am doing it now is in the library's properties, I set the "Post-build event command line" to: copy "$(TargetPath)" "$(SolutionDir)\MyWebsite\bin\$(TargetFileName)"
Every time I want a new website to use the shared library, I add a new line like this: copy "$(TargetPath)" "$(SolutionDir)\MyWebsite2\bin\$(TargetFileName)"
Is there an easy or better way to do this besides using the GAC?
In my opinion your problem here is a lack of control about how this library is produced and used by other projects. If I were you (which I'm not :) I'd set about developing the library through a unit test co-project where new functionality can be developed and tested independently. Once that functionality has been implemented and tested to be working within your unit test parameters manually copy the assembly into a "library" folder of the web project that the required the extension of the library in the first place (this folder holds all your compiled assemblies used by that project).
Even better would be to maintain a version system in which you tag the new version of the library so as to keep track of the exact source revision that it's using.
The reason I suggest what may seem like a cumbersome methodology of working is that your current practice makes your existing websites quite brittle as a change made in the library for one site may in fact break one of the other sites... and as the amount of sites you have increases you can't be forever retro testing new versions of the shared library against the existing sites.
It's also for these reasons that I don't recommend using the GAC either.