RadImageGallery - how to trap exception when binding to binary images

1 Answer 104 Views
ImageGallery UI for ASP.NET AJAX in ASP.NET MVC
Margo Noreen
Top achievements
Rank 1
Iron
Veteran
Margo Noreen asked on 04 Jun 2024, 04:02 PM | edited on 07 Jun 2024, 08:54 AM

We have the RadImageGallery implemented on page. The code behind loads up one or more images by reading in an array of bytes from each file.  Occasionally, an exception is thrown when one of those images is invalid (corrupt or some other issue).  OK, that's fine, but we would like to trap the exception and handle the error in a particular way.  But... we don't seem to be able to trap it other than in our last-chance global exception handler.

The binary data is created in the NeedDataSource event, and that returns successfully.  I've added other events and set breakpoints in each of them, and they all return ok.  So, is there an event we can handle that would be appropriate for a simple try/catch block?

Pretty simple markup for the RadImageGallery control (note, all the events after the OnNeedDataSource were added simply to test out if there was a place we could try/catch the exception, but no exception was thrown in those events):

    <telerik:RadImageGallery ID="galleryImages" runat="server" RenderMode="Lightweight"
        DisplayAreaMode="Image" LoopItems="true" DataImageField="ImageBytes" DataDescriptionField="Description" DataTitleField="Title"
        OnNeedDataSource="galleryImages_NeedDataSource"
        OnDataBinding="galleryImages_DataBinding"
        OnImageRequested="galleryImages_ImageRequested" 
        OnItemCreated="galleryImages_ItemCreated" 
        OnPreRender="galleryImages_PreRender">
    </telerik:RadImageGallery>

 

Code behind for NeedDataSource (which returns successfully):

    protected void galleryImages_NeedDataSource(object sender, Telerik.Web.UI.ImageGalleryNeedDataSourceEventArgs e)
    {
        galleryImages.Visible = false;

        FileManager fileManager = new FileManager ();
        DataTable dt = fileManager.GetFileList();
        var imageFiles = fileManager.GetGalleryImages(dt);

        if (imageFiles.Count() == 0)
        {
            txtNotes.Text = "There are no image files to display.";
            return;
        }

        try
        {
            galleryImages.DataSource = imageFiles;
            galleryImages.Visible = true;
        }
        catch (Exception ex)
        {
            LogException(ex);
            ErrorMessage("An unexpected occurred while reading one or more the image files");
        }

        if (fileManager.HasErrors)
        {
            txtErrors.Text = "The following errors were encountered:<br/><ul>" + String.Join("<li>", fileManager.ErrorList) + "</ul>";
        }
    }

 

Library code that reads image files into byte arrays (also return successfully):

        public List<GalleryImage> GetGalleryImages(DataTable srcDataTable)
        {

            //...


            foreach (DataRow dr in query)
            {
                CustomImageFile f = new CustomImageFile(dr);                

                try
                {
                    byte[] byteArray = File.ReadAllBytes(f.FullFileName);
                    GalleryImage img = new GalleryImage
                    {
                        ImageBytes = byteArray,
                        Description = $"{f.Description}", // [{f.Name}]
                    };
                    imageList.Add(img);
                }
                catch (Exception ex)
                {
                    Errors.Add($"{f.Name} could not be read");
                    LogException(ex);                    
                }
            }
            return imageList;
        }

 

Yet when there is an invalid file encountered, we get this:

[ArgumentException: Parameter is not valid.]
   System.Drawing.Image.FromStream(Stream stream, Boolean useEmbeddedColorManagement, Boolean validateImageData) +1162080
   Telerik.Web.UI.BinaryImageFormatHelper.CreateImgFromBytes(Byte[] data) +69

[ArgumentException: The provided binary data may not be valid image or may contains unknown header]
   Telerik.Web.UI.BinaryImageFormatHelper.CreateImgFromBytes(Byte[] data) +120
   Telerik.Web.UI.BinaryImageTransformationFilter.ProcessImageInternal(Byte[] image) +44
   Telerik.Web.UI.BinaryImageTransformationFilter.ProcessImage(Byte[] image) +20
   Telerik.Web.UI.BinaryImageFilterProcessor.ProcessFilters(Byte[] imageData) +112
   Telerik.Web.UI.RadBinaryImage.ProcessImageData() +57
   Telerik.Web.UI.RadBinaryImage.OnPreRender(EventArgs e) +20
   System.Web.UI.Control.PreRenderRecursiveInternal() +90
   System.Web.UI.Control.PreRenderRecursiveInternal() +163

 

1 Answer, 1 is accepted

Sort by
0
Attila Antal
Telerik team
answered on 07 Jun 2024, 09:18 AM

Hi Margo,

The RadImageGallery implements the ASP.NET Framework's System.Drawing.Image Class, which will try to create an Image object from the byte array, but because the file is corrupted, the operations fails. The issue could be replicated with the Image class as well.

Here is an example that would throw the same error.

byte[] byteArray = // your image bytes
using(MemoryStream ms = new MemoryStream())
{
    ms.Write(byteArray, 0, byteArray.Length);

    System.Drawing.Image img = System.Drawing.Image.FromStream(ms);
}

 

To void that issue, you can implement an additional feature that will verify the image bytes before they are even assigned to the RadImageGallery.

Here are two examples suggested by others to verify if the image is corrupted: 

Here is an example of how this could be achieved. In the GetGalleryImages method, you will call on your helper method that will verify the byte array by trying to convert it into an image before storing the data in the DataTable. If the image is corrupted, it will skip and do the next one.

public List<GalleryImage> GetGalleryImages(DataTable srcDataTable)
{

    //...

    foreach (DataRow dr in query)
    {
        CustomImageFile f = new CustomImageFile(dr);

        try
        {
            byte[] byteArray = File.ReadAllBytes(f.FullFileName);

            if (!IsValidImage(byteArray)) continue;

            GalleryImage img = new GalleryImage
            {
                ImageBytes = byteArray,
                Description = $"{f.Description}", // [{f.Name}]
            };
            imageList.Add(img);
        }
        catch (Exception ex)
        {
            Errors.Add($"{f.Name} could not be read");
            LogException(ex);
        }
    }
    return imageList;
}

private bool IsValidImage(byte[] imageData)
{
    // Implement one of the two solutions here that will verify the image
}

I hope this will help resolve the issue.

Regards,
Attila Antal
Progress Telerik

Stay tuned by visiting our public roadmap and feedback portal pages! Or perhaps, if you are new to our Telerik family, check out our getting started resources
Tags
ImageGallery UI for ASP.NET AJAX in ASP.NET MVC
Asked by
Margo Noreen
Top achievements
Rank 1
Iron
Veteran
Answers by
Attila Antal
Telerik team
Share this question
or