Răsfoiți Sursa

Allow base64 encoded strings to be deserialized as byte arrays in JSInterop (#33768)

As part of https://github.com/dotnet/announcements/issues/187, JSInterop required
byte arrays to be written as UInt8 js arrays and read using a new js API.
This change intentionally broke support for sending byte arrays as base64 strings.

Through testing, we found at least one use case (dotnet-watch) that currently passes a base64 string via JSInterop. We can
trivially support both formats to retain back-compat in this one case.

This reduces the extent of the breaking change by allowing base-64 encoded strings to be sent from JS to .NET.

Low. The change is specific to reading byte arrays via JSInterop and does not have any broad impact outside of this.

* [x] Automated
* [x] Manual (using dotnet-watch)
Pranav K 4 ani în urmă
părinte
comite
8dee7b089d

+ 7 - 2
src/JSInterop/Microsoft.JSInterop/src/Infrastructure/ByteArrayJsonConverter.cs

@@ -2,7 +2,6 @@
 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
 
 using System;
-using System.Diagnostics.CodeAnalysis;
 using System.Text.Json;
 using System.Text.Json.Serialization;
 
@@ -24,9 +23,15 @@ namespace Microsoft.JSInterop.Infrastructure
 
         public override byte[]? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
         {
+            // For back-compat reasons, try reading the input as a base-64 encoded string at first.
+            if (reader.TokenType == JsonTokenType.String && reader.TryGetBytesFromBase64(out var bytes))
+            {
+                return bytes;
+            }
+
             if (JSRuntime.ByteArraysToBeRevived.Count == 0)
             {
-                throw new JsonException("ByteArraysToBeRevived is empty.");
+                throw new JsonException("JSON serialization is attempting to deserialize an unexpected byte array.");
             }
 
             int byteArrayRef;

+ 28 - 1
src/JSInterop/Microsoft.JSInterop/test/Infrastructure/ByteArrayJsonConverterTest.cs

@@ -24,7 +24,7 @@ namespace Microsoft.JSInterop.Infrastructure
 
             // Act & Assert
             var ex = Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<byte[]>(json, JsonSerializerOptions));
-            Assert.Equal("ByteArraysToBeRevived is empty.", ex.Message);
+            Assert.Equal("JSON serialization is attempting to deserialize an unexpected byte array.", ex.Message);
         }
 
         [Fact]
@@ -66,6 +66,33 @@ namespace Microsoft.JSInterop.Infrastructure
             Assert.IsAssignableFrom<JsonException>(ex);
         }
 
+        [Fact]
+        public void Read_ReadsBase64EncodedStrings()
+        {
+            // Arrange
+            var expected = new byte[] { 1, 5, 8 };
+            var json = JsonSerializer.Serialize(expected);
+
+            // Act
+            var deserialized = JsonSerializer.Deserialize<byte[]>(json, JsonSerializerOptions)!;
+
+            // Assert
+            Assert.Equal(expected, deserialized);
+        }
+
+        [Fact]
+        public void Read_ThrowsIfTheInputIsNotAValidBase64String()
+        {
+            // Arrange
+            var json = "\"Hello world\"";
+
+            // Act
+            var ex = Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<byte[]>(json, JsonSerializerOptions));
+
+            // Assert
+            Assert.Equal("JSON serialization is attempting to deserialize an unexpected byte array.", ex.Message);
+        }
+
         [Fact]
         public void Read_ReadsJson()
         {