Resolving conflicting version requirements for NewtonSoft.Json - json.net

I have read several postings about assembly binding issues and have tried many of the proposed solutions, all with no luck.
I have a relatively old asp.net web forms web site. It depends on a .Net Framework 4.6 Analytics assembly that in turn depends on NewtonSoft.Json. That Analytics assembly is one of our own and was built with NewtonSoft.Json v7.0.1. That is the version of the assembly that resides in the web site's bin folder.
I have a newer web site, an Angular SPA, that relies on .Net Framework WebApi services. The services rely on a logging helper component that calls a separate logging service. The logging helper component depends on Microsoft.AspNet.WebApi.Client to make the service call, which depends on System.Net.Http.Formatting, which depends on NewtonSoft.Json v6.0.4.
When I try to use the new logging helper component in the web site, at runtime, the logging fails saying that it cannot load v6.0.0.0 of NewtonSoft.Json or one of its dependencies.
If I drop the v7.0 file in the web site bin folder, the web site fails because the Analytics assembly cannot load v7.0.0.0 of NewtonSoft.Json or one of its dependencies.
Ideally I'd like to have Microsoft.AspNet.WebApi.Client and System.Net.Http.Formatting play nicely with the newer version of NewtonSoft.Json, but I don't have much control over how those assemblies play. I've tried rebuilding my Analytics component with NewtonSoft.Json v6.0.4, but when it gets built and deployed, somehow on the web server it still ends up looking for v7.0.0.0.
I feel like I'm stuck between a rock and a hard place. I can either have my Analytics work or my Logging work, but I cannot get both to work. Any suggestions as to a) what direction to pursue for a solution - getting my Analytics component to accept the older version or getting my Logging component to work with the newer version and b) how to accomplish either of those approaches?
Update 1 - Some of the things I've tried beyond what I've described above:
In my logging helper component .csproj project file, I tried eliminating the version information from my NewtonSoft.Json reference. I deployed it into the web site with the NewtonSoft.Json v7.0 file, but it still failed saying it couldn't load v6.0.
I tried using fuslogvw.exe, the Assembly Binding Log Viewer. Maybe I wasn't using it right, but I could reproduce my assembly binding error and saw nothing at all the Assembly Binding Log Viewer.
Update 2 - I tried adding an assembly binding redirect in my logging helper component redirecting it from 6.0.0.0 to 7.0.0.0, but when I build the component and drop it in the web site bin folder, which now has the NewtonSoft.Json 7.0 file, the logger still fails saying that it can load v6.0.0.0. Is there no way out of this?
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="NewtonSoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
<bindingRedirect oldVersion="6.0.0.0"
newVersion="7.0.0.0" />
</dependentAssembly>
</assemblyBinding>
Update 3 - Below is the packages.config from the logging helper component. I believe that everything in packages.config is based on my adding the Microsoft.AspNet.WebApi.Client package. According to the package info on NuGet, it should work with NewtonSoft.Json >= 6.0.4, but it always fails looking for 6.0.0.0.
<packages>
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.6" targetFramework="net461" />
<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="1.0.5" targetFramework="net461" />
<package id="Microsoft.Net.Compilers" version="2.4.0" targetFramework="net461" developmentDependency="true" />
<package id="Newtonsoft.Json" version="6.0.4" targetFramework="net461" />
<package id="System.Net.Http" version="2.0.20126.16343" targetFramework="net461" />
</packages>

I'm not entirely satisfied with this answer, but it does appear to work. I read through several more posts on this topic, specifically posts about issues with version conflicts with NewtonSoft.Json, which seems to have conflicts quite often. In this article several people reported that the assembly binding redirects only worked if they were in machine.config. I had been trying to add assembly binding redirects in my logging helper component config file. I realize now that since I had a runtime binding error, I needed to work on the configuration of the runtime application, i.e. the web site. But adding the bind redirects to web.config seems to have no effect, while adding them to machine.config works. Unfortunately it breaks other applications on the server that need a different version. So... sort of an answer, but not all the way there yet. Here is the binding redirect that, when added to machine.config on the web server, gets the logging helper component working correctly in the web site.
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="NewtonSoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
<bindingRedirect oldVersion="6.0.0.0" newVersion="7.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
But I still need to figure out how to get the other applications on the server to work correctly. This problem seems to never end.
Update: I have a working solution, at least in my Dev and Test environments. The solution involves the assembly binding redirect in machine.config as described above plus installing the desired version of the assembly into the Global Assembly Cache (GAC) so that it's available to all applications on the server.
It's not my favorite solution and I'd still be happy to hear alternatives, but for now, this is what I've got and it seems to work. Only problem left is getting the assembly into the GAC on Production servers that don't have Visual Studio or Windows SDK installed - so no gacutil.exe utility.

Related

Failed to find a valid digest in the 'integrity' attribute for resource in Blazor app

I have a Blazor client/server app that I have been working on for a period and it has been working fine up to now. I suddenly started getting this error
Failed to find a valid digest in the 'integrity' attribute for
resource 'https://mydomain.no/_framework/Faso.Blazor.SpinKit.dll'
with computed SHA-256 integrity
'1UEuhA1KzEN0bQcoU0m1eL4WKcCIWHhPgoXydAJnO9w='. The resource has been
blocked.
Failed to find a valid digest in the 'integrity' attribute for resource
I have tried to clean and rebuild. I have tried to add Cors, set folder permission, and many other suggested solutions, but to no avail. I am using web deploy in VS 2022 and Win Server 2016, .net core 5.0.
Any suggestions would be appreciated.
This is an annoying issue indeed and I'm getting that error every now and then. It seems to happen after updating some packages, and the build processes fails to pick up the new SHA for the package.
You can verify that this is the issue by finding the file containing the SHAs and compare the SHA for the dll in question with the SHA from the error message.
This file is called blazor.boot.json and is generated deep inside the obj-folder of your project folder.
(mine was here: obj\Release\net6.0\win-x86\PubTmp\Out\wwwroot\_framework)
If was the issue, please try this:
Close VS.
Delete the obj and bin folders from all your projects. (the web project might be enough, but hey - can't hurt)
Start VS
Rebuild solution.
Try Publish again.
All answers here are great.
The only caveat to my solution was that I was using a hosted Blazor WASM model. Since we publish our Server application, it takes the liberty to build the Client for us. After seeing every single solution say to delete your bin and obj folder and then banging my head on every wall in our office it finally dawned on me that I don't need to be deleting the bin and obj from my "Server" project and that I might need to go to the Client project and do that.
It might sound simple enough in hindsight, but coffee failed me this morning. At the expense of my pride.. hopefully this can be someone's light bulb answer. Sometimes YOU are the little things. :D
I finally solved it for my own issue! This issue has been plaguing me for weeks.
I had tried all of the things mentioned here and elsewhere, and none of it worked. What did work was using my ftp client (filezilla) and changing the transfer type from "auto" to "binary" (Transfer > Transfer Type > Binary). I don't see an option for doing this in VS2022, so I guess I'll use my manual ftp client solution for now.
Aaaahhhhh.
Check this note from: https://learn.microsoft.com/en-us/aspnet/core/blazor/host-and-deploy/webassembly?view=aspnetcore-6.0
Resolve integrity check failures:
When Blazor WebAssembly downloads an app's startup files, it instructs the browser to perform integrity checks on the responses. Blazor sends SHA-256 hash values for DLL (.dll), WebAssembly (.wasm), and other files in the blazor.boot.json file, which isn't cached on clients. The file hashes of cached files are compared to the hashes in the blazor.boot.json file. For cached files with a matching hash, Blazor uses the cached files. Otherwise, files are requested from the server. After a file is downloaded, its hash is checked again for integrity validation. An error is generated by the browser if any downloaded file's integrity check fails.
If after deleted obj and bin folders the error continues, be sure that you are deleting the cache on your client browser of the site (Ctrl + F5)
My solution is also so interesting. I put my web api service and Blazor Wasm projects into same server with different subdomains. Both of them are using .Net 6.
Although Web Api works well, Blazor gave that error. I tried everything on the StackOverflow, none of them worked. Then I tried to move Blazor project to another server that another Blazor Wasm is already working and Bingo!
While it gave problem in Windows Server 2022 with IIS 10.0.20348.1 and .Net Core Hosting Bundle 6.0.7; it worked in first try with the same files in Windows Server 2019 with IIS 10.0.17763.1 and .Net Core Hosting Bundle 6.0.6
I am really so surprised that why it gave error in new server and I couldn't understand where is the problem exactly (Server edition, IIS or .Net minor version differences)
I hope it helps to someone that couldn't solve problem yet.
For me (I've updated the SDK from .NET 6 to 7), the solution was the following order of action:
Clear all bin and obj folders
Clear all nuget cache instruction
Run the app and clear the browser cache (Ctrl+F5)
For me it was wrong MIME Types.
There was a web.config with changes to Mime types, but I needed to mannually change it for my Blazor Page in IIS.
After this it worked
Web.config in Publish folder contained a section like this:
<remove fileExtension=".blat" />
<remove fileExtension=".dat" />
<remove fileExtension=".dll" />
<remove fileExtension=".json" />
<remove fileExtension=".wasm" />
<remove fileExtension=".woff" />
<remove fileExtension=".woff2" />
<mimeMap fileExtension=".blat" mimeType="application/octet-stream" />
<mimeMap fileExtension=".dll" mimeType="application/octet-stream" />
<mimeMap fileExtension=".dat" mimeType="application/octet-stream" />
<mimeMap fileExtension=".json" mimeType="application/json" />
<mimeMap fileExtension=".wasm" mimeType="application/wasm" />
<mimeMap fileExtension=".woff" mimeType="application/font-woff" />
<mimeMap fileExtension=".woff2" mimeType="application/font-woff" />
This conflicted with the Mime Settings in IIS
After I changed the Mime Settings in IIS to the values from the web.config, it worked.
For me, it happens if I run the same blazor app in the same browser user but with different domains. ex:
'mywebsite.z13.web.core.windows.net' and 'mywebsite.com'
Delete the cache, and run only 1 domain per browser user.

Using ELMAH with ASP.NET WebApp with a Class library

I have an ASP.NET 4.5 Web Application (running on IIS 7.5), which calls a method from a class library I have referenced.
I want to add ELMAH to log when I have unhandled exceptions.
I have installed ELMAH with NuGet. It works great.
The problem is that it doesn't log any exceptions coming from the class library, it only logs the ones coming from the web application.
I tried adding a try catch in my class library and tried to log the exception manually with:
ErrorSignal.FromCurrentContext().Raise(e);
But this doesn't do anything.
Do I have to install and reference ELMAH on both web application and class library ? And will the web.config be enough for the class library to know which handlers and modules to use ? Or do I need to add another config in the class library ?
I noticed that both web app and class library have a packages.config but it only contains:
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="elmah" version="1.2.2" targetFramework="net45" />
<package id="elmah.corelibrary" version="1.2.2" targetFramework="net45" />
</packages>
I have found many pages on stackoverflow about this topic but couldn't find an answer that works for me.
Some people recommended using
ErrorLog.GetDefault(HttpContext).Log(new Error(errExc));
But HttpContext is not available. I tried using null instead of HttpContext but it didn't help either.
While searching online, I found out that ELMAH only logs the stuff coming from the web app. I was able to log the stuff coming from the class library by installing NLog or using System.Diagnostic.Trace.
Perhaps I'm wrong about this, and I'd be open to corrections.

Security Critical Method constructor error with MVC 5

I've been trying to get an MVC 5 web application running on a server. It has not been a good day :-(
The server is Windows Server 2008. I have installed NET Framework 4 and NET Framework 4.5. I spent ages trying to get past a really weird 403 Access Forbidden error before discovering that adding this attribute gets the site loading.
<modules runAllManagedModulesForAllRequests="true">
I am now getting an error within an internal constructor that seems to be called before my Application_Start method. I am using the Membership Database, since I've upgraded an MVC 3 project to MVC 5. I mention this since I've seen a few questions on SO where people have encountered this problem using OpenAuth.
From what I've read the problem is connected to the security model changing. This question is one such example.. However, the AllowPartiallyTrustedCallersAttribute is not available in MVC 5.
I've ran the project successfully on my local machine but pushing it to a server is looking a touch tricky. I suspect there is something not quite right with the set up on the server but I'm at a bit of a loss now to guess what.
EDIT
The problem is with the recommended version of System.Web.WebPages. If I comment that out in my web.config then the project runs. It doesn't look as nice as it should be it definitely runs! I've going to try and install this web app on a server running Windows 2008 R2 Datacentre. I'll post my results.
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
Make sure you follow, completely, the instructions for upgrading you site to MVC5. I had this same issue until I followed these instructions: http://www.asp.net/mvc/tutorials/mvc-5/how-to-upgrade-an-aspnet-mvc-4-and-web-api-project-to-aspnet-mvc-5-and-web-api-2.
The fix that worked for me was to remove System.Web.WebPages. I was only using in my application because I was using TagBuilder in one class. I can use strings and string.Format instead and now I have an application that works.
I installed my app on a Windows 2008 R2 DataCentre server and encountered the same problem. The fix was the same remove System.Web.WebPages.
Seems bizarre that a DLL with a name that sounds so fundamental doesn't work and can be discarded.
EDIT
My NUnit tests on my build server didn't like the missing DLL, although running them locally on my machine showed no problems at all. The solution was to add the DLL to my test project. I suspect some of my problems are to do with TeamCity not being quite up to date with Visual Studio 2013.
EDIT
I have found a better fix to this solution which does not involve removing the System.Web.WebPages DLL. I'll post the answer soon.
To fix this problem there were two steps: first remove Nuget packages that came with the default set up but which I was not using. These included Owin, Microsoft.Owin and various others connected with Identity. The only package I needed was Microsoft.AspNet.Identity.Core because I am using User.Identity.Name.
The second step was to exclude those files that used the packages: these were the AccountController, Startup.cs and Startup.Auth.cs in the App_Start folder. I think these files are necessary if using the newer versions of Authenticaion but as I am using the old MembershipProvider they are not necessary for me.

SQLite Assembly Error in VS 2010

I'm trying to develop a settings application whererby a developer can download a zip file containing a SQLite database and the relevant DLL's and simple use it by calling Setting.Set and Setting.Get in their code. Using a simple Key/Value pair in the database, this lets users store any setting, for anything.
However, I keep getting the error:
"Could not load file or assembly 'System.Data.SQLite, Version=1.0.66.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139' or one of its dependencies. The system cannot find the file specified."
...when trying to integrate it into a new test app.
I've tried the
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0"/>
<requiredRuntime version="v4.0.20506"/>
</startup>
</configuration>
section in the App.config but this doesn't fix the problem.
I'm trying to make the "plug-in" as easy as possible for the end user/developer for re-usability but this is becoming very tedious indeed! >:-(
Any ideas guys?
Thank you for your help!!
You can start by using the latest System.Data.SQLite assembly:
http://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki
Somewhere on that page you'll find "Precompiled Statically-Linked Binaries for 32-bit Windows (.NET Framework 4.0)" which should be fine for packaging the System.Data.SQLite assembly with your app.
This should also allow you to not use the useLegacyV2RuntimeActivationPolicy="true" application setting.

How can I organize my dll's into multiple folders under the bin directory in ASP.NET?

How can I take several dll's in my bin folder for my ASP.NET application organize them into seperate folders and leave them under the bin directory so that they still are readily accesible to the application as if they were in the root of the bin? I want to reduce the monstrous list of dlls and group them into folders related to their core purpose.
You can make your application probe other directories for loading assemblies by using the web.config file and specifying a <probing> element. I'm unclear as to whether or not this works now with website type projects, as it did not several years ago. It should, however, work with Web Application type projects.
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="bin\subdir"/>
</assemblyBinding>
</runtime>
<system.web>
....
....
</system.web>
</configuration>
Don't do that. Even if it works, it will not be understood by anyone else.
If you're bothered by the number of assemblies in the bin folder, then don't look there.
There was an article Moving the Code-Behind Assemblies/DLLs to a different folder than /BIN with ASP.NET 1.1
I suppose the approach with using assemblyBinding Element for runtime can work for .NET 2.0 too
But I agree that it is not recommended...
Are you trying to organize the dlls generated by the app after compilation or the 3rd party and external dlls used by your app?
If it is the latter and you are not doing so already you can organize these into any hierarchy you choose outside the app (but inside the solution). You can then reference the dlls from there.
Trying to organize the asp.net compiler generated files feels like swimming upstream.

Resources