'Blob Storage infrastructure IBlobContainer relies on deprecated mechanism. How should I fix this?

I am implementing the BLOB Storing capability provided through the Volo.Abp.BlobStoring.IBlobContainer interface.

I believe I have everything coded and configured correctly but a recent deprecation by Microsoft has me wondering if there is a better implementation than what I am attempting.

Here is my code:

  public async Task StorePhotoAsync(Photo photo)
  {
    var photoBytes = ObjectToByteArray(photo);
    await _blobContainer.SaveAsync(photo.Id.ToString(), photoBytes);
  }

  // TODO - Reimplement (deprecated serialization) - JLavallet 2022-03-09 10:41 
  private byte[] ObjectToByteArray(object obj)
  {
    if (obj == null)
    {
      return null;
    }

    var bf = new BinaryFormatter();
    using var ms = new MemoryStream();
    bf.Serialize(ms, obj);

    return ms.ToArray();
  }

  // TODO - Reimplement (deprecated serialization) - JLavallet 2022-03-09 10:41 
  private object ByteArrayToObject(byte[] arrBytes)
  {
    using var memStream = new MemoryStream();
    var binForm = new BinaryFormatter();
    memStream.Write(arrBytes, 0, arrBytes.Length);
    memStream.Seek(0, SeekOrigin.Begin);
    var obj = binForm.Deserialize(memStream);

    return obj;
  }

As you can see from my to do comments and the screenshot below, there is a deprecation of the Serialize and Deserialize methods of the BinaryFormatter:

IntelliSense help for the Serialize method

Could anyone suggest an alternative approach? The IBlobContainer only wants to save a byte array.



Solution 1:[1]

So after Mr. T set me straight, I read the documentation for JSON UTF8 serialization and deserialization, and here's what I came up with:

  public async Task StorePhotoCacheItemAsync(PhotoCacheItem photoCacheItem)
  {
    var bytes = PhotoCacheItemToByteArray(photoCacheItem);
    await _blobContainer.SaveAsync(photoCacheItem.Id.ToString(), bytes);
  }

  private byte[] PhotoCacheItemToByteArray(PhotoCacheItem photoCacheItem)
  {
    if (photoCacheItem == null)
    {
      return null;
    }

    // the old way
    //var bf = new BinaryFormatter();
    //using var ms = new MemoryStream();
    //bf.Serialize(ms, obj);

    // a new way
    //using var ms = new MemoryStream();
    //using var writer = new Utf8JsonWriter(ms);
    //JsonSerializer.Serialize(writer, photoCacheItem);
    //return ms.ToArray();

    // a better new way
    var bytes = JsonSerializer.SerializeToUtf8Bytes(photoCacheItem);
    return bytes;
  }

  private async Task<PhotoCacheItem> GetPhotoCacheItemFromBlobStorage(Guid photoId)
  {
    var bytes = await _blobContainer.GetAllBytesOrNullAsync(photoId.ToString());
    if (bytes == null)
    {
      return null;
    }

    var photoCacheItem = ByteArrayToPhotoCacheItem(bytes);
    return photoCacheItem;
  }

  private PhotoCacheItem ByteArrayToPhotoCacheItem(byte[] bytes)
  {
    // the old way
    //using var ms = new MemoryStream();
    //var bf = new BinaryFormatter();
    //ms.Write(bytes, 0, bytes.Length);
    //ms.Seek(0, SeekOrigin.Begin);
    //var obj = bf.Deserialize(ms);

    // a new way
    //var utf8Reader = new Utf8JsonReader(bytes);
    //var photoCacheItem = JsonSerializer.Deserialize<PhotoCacheItem>(ref utf8Reader)!;

    // a better new way
    var readOnlySpan = new ReadOnlySpan<byte>(bytes);
    var photoCacheItem = JsonSerializer.Deserialize<PhotoCacheItem>(readOnlySpan)!;

    return photoCacheItem;
  }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 jlavallet