2

I have migrated a couple of ASP.Net Core 2.2 projects to .Net 5, the last issue I have is that I get a System.NotSupported exception when trying to load bitmaps from the project resources.

RtfUtility.AppendLogo(result, Properties.Resources.Logo);

System.NotSupportedException HResult=0x80131515 Message=BinaryFormatter serialization and deserialization are disabled within this application. See https://aka.ms/binaryformatter for more information. Source=System.Runtime.Serialization.Formatters

I'm not using BinaryFormatter explicitly but oddly I don't get an error when loading a binary PDF file in the same way:

processor.LoadDocument(new MemoryStream(Properties.Resources.Certificate));

Both mechanisms use ResourceManager.GetObject, so I'm not sure whats going on. I know I can turn off the error in the project file, but that seems to be a short term solution, I'd rather fix it and forget it. Thanks for any advice you can give...

Edit:

Stack Trace is below, The error is not caused by the library, it is when accessing the resource. It happens when the image is embedded or linked - seems to make no difference, but doesn't happen with a (binary) PDF file.

Thanks for looking at this...

at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream) at System.Resources.ResourceReader.<>c__DisplayClass7_0`1.b__0(Object obj, Stream stream) at System.Resources.ResourceReader.DeserializeObject(Int32 typeIndex) at System.Resources.ResourceReader._LoadObjectV2(Int32 pos, ResourceTypeCode& typeCode) at System.Resources.ResourceReader.LoadObjectV2(Int32 pos, ResourceTypeCode& typeCode) at System.Resources.ResourceReader.LoadObject(Int32 pos, ResourceTypeCode& typeCode) at System.Resources.RuntimeResourceSet.GetObject(String key, Boolean ignoreCase, Boolean isString) at System.Resources.RuntimeResourceSet.GetObject(String key, Boolean ignoreCase) at System.Resources.ResourceManager.GetObject(String name, CultureInfo culture, Boolean wrapUnmanagedMemStream) at System.Resources.ResourceManager.GetObject(String name, CultureInfo culture) at Project.Infrastructure.Properties.Resources.get_Logo() in C:\Development\Project\Project.Infrastructure\Properties\Resources.Designer.cs:line 227 at Project.Infrastructure.Models.ShowWording.Generate() in C:\Development\Project\Project.Infrastructure\Models\ShowWording.cs:line 146

Ian Gordon
  • 39
  • 1
  • 1
  • 4
  • Is the bitmap resource an embedded one or is it linked to a file? – Steeeve Nov 01 '21 at 12:12
  • 2
    Adding full stack trace might help – Evk Nov 01 '21 at 12:20
  • The line throwing the exception from the reference source. https://referencesource.microsoft.com/#mscorlib/system/resources/resourcereader.cs,798 . The PDF is probably falling in the the `ByteArray` or `Stream` handling in the switch, while the image is falling into the "User Types", which always throws an exception if `FEATURE_SERIALIZATION` is turned off. It isn't actually TRYING to deserialize the type, it's just saying that the feature is disabled. Images probably shouldn't be using the User Types. – Bradley Uffner Nov 02 '21 at 16:16
  • Could you post the contents of the Resources.resx file? Or create a new .NET 5 project, add a bitmap resource and compare the files. There should be some differences, but I don't have such a resources.resx from an old project. – Steeeve Nov 02 '21 at 17:23

5 Answers5

5

BinaryFormatter serialization methods are obsolete and prohibited in ASP.NET apps. However, the article does not say anything about the resourceReader or other classes, even if the same security warning applies.

So I would presume that this is a bug. At a minimum I would have expected the documentation to explicitly state that binary resources are not supported, or any other compatibility constraints. I would consider creating a minimal reproducible example to ensure there is no other weird build issue causing the problem, and posting a bug report about it.

Note that there seem to be various issues reported about binary resources in .net core, but it is unclear to me what the final resolution is.

As a workaround there is an option to re enable binaryformatter in .Net 5 asp.Net apps by adding the following to the project file.

<PropertyGroup>
  <TargetFramework>net5.0</TargetFramework>
  <!-- Warning: Setting the following switch is *NOT* recommended in web apps. -->
  <EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
</PropertyGroup>
JonasH
  • 28,608
  • 2
  • 10
  • 23
  • 1
    I think this workaround is known to Ian, he is trying not to use it. – Steeeve Nov 01 '21 at 12:15
  • @steeeve I would assume `RtfUtility.AppendLogo` is a third party library, If so, I do not see any other way to fix the issue other than updating the library. If binaryFormatter is used by the .net 5 API itself it would presumably be a bug, and should be reported. – JonasH Nov 01 '21 at 12:21
  • 1
    For me it sounds that accessing Properties.Resources.Logo is causing the exception, but let us wait for the StackTrace ;) – Steeeve Nov 01 '21 at 12:24
  • The exception is raised when accessing the resource, not the 3rd party library. I seperated them out and the error still occurred. Linking or embedding the image doesn't seem to make any difference... – Ian Gordon Nov 02 '21 at 13:33
2

Add the following property group to your .csproj file:

<PropertyGroup>
  <TargetFramework>net6.0</TargetFramework>
  <!-- Warning: Setting the following switch is *NOT* recommended in web apps. -->
  <EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
</PropertyGroup>
Liquid Core
  • 1
  • 6
  • 27
  • 52
1

It seems that Visual Studio/.Net previously made images added as resources accessible as Image, which makes use of the BinaryFormatter, while if I now add images they are accessible as byte[].

I was able to update the resource file to only return byte[] by simply:

  1. Replacing System.Drawing.Bitmap with byte[] in the *.Designer.cs file
  2. Replacing System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a with System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 in the *.resx file

Previously :

// In the *.Designer.cs file
public static System.Drawing.Bitmap MyImage {
  get {
    object obj = ResourceManager.GetObject("MyImage", resourceCulture);
    return ((System.Drawing.Bitmap)(obj));
  }
}

// In the *.resx file
<data name="MyImage" type="System.Resources.ResXFileRef, System.Windows.Forms">
    <value>Path\To\MyImage.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
  </data>

Now:

// In the *.Designer.cs file
public static byte[] MyImage {
  get {
    object obj = ResourceManager.GetObject("MyImage", resourceCulture);
    return ((byte[])(obj));
  }
}

// In the *.resx file
<data name="MyImage" type="System.Resources.ResXFileRef, System.Windows.Forms">
    <value>Path\To\MyImage.jpg;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value></value>
  </data>
user276648
  • 6,018
  • 6
  • 60
  • 86
0

I found a workaround, that doesn't make sense, but I trust it more than allowing unsafe Binary Formatters in my projects.

Following on from your suggestions I tried deleting and recreating the resource file, removing and re-adding the affected image, but nothing worked.

So, because reading a pdf file worked, I removed the .png extension from my image and saved it as a File resource.

I can now read it from resources as binary and convert it to Bitmap and it works fine.

using (var ms = new MemoryStream(Properties.Resources.LogoBinary))
{
   return  new Bitmap(ms);
}

I can't believe this is a bug in the framework, as it would affect a lot of people, it must be something peculiar to my project, but it is odd that I get the BinaryFormatter exception when reading an image, but not a Binary file...

Thanks everyone for your guidance & assistance...

Ian Gordon
  • 39
  • 1
  • 1
  • 4
0

Microsoft is getting rid of BinaryFormatter, which is totally understandable.

it is odd that I get the BinaryFormatter exception when reading an image, but not a Binary file

A binary file is not serialized by BinaryFormatter but saved as a simple byte array or added as a special resource that can be accessed as a memory stream. Actually you can make images to be accessible as streams in the resource files pretty easily (the linked answer focuses for WPF compatibility for the image resources but the first part still applies).

In case you still need to read old resource files in .NET Core/.NET that contain BinaryFormatter resources you can use my own resource handling libraries that can work directly on .resx files (GitHub), which ironically provides better backward compatibility with legacy resource files than .NET Core/.NET itself. It also supports saving resources in legacy format. But please note that when targeting .NET 8 or later, BinaryFormatter compatibility will not work anymore even by this library.

György Kőszeg
  • 17,093
  • 6
  • 37
  • 65