xamarin.formsimagesource

Load Image from URL with a Referrer Header


I need to download static images from my CDN and display them in my Xamarin.Forms view. I'm new to Xamarin specifically and I'm having a hard time figuring out how to load an image from a byte array pulled from a HTTP request.

I have the following XAML in my View:

    <ListView ItemsSource="{Binding Images}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ImageCell ImageSource="{Binding .}">
                    
                </ImageCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

In my code behind I'm fetching the image and trying to bind to a Collection of ImageSource instances.

    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }

        public ObservableCollection<ImageSource> Images { get; set; } = new ObservableCollection<ImageSource>();

        protected override async void OnAppearing()
        {
            base.OnAppearing();

            var client = new HttpClient();
            client.DefaultRequestHeaders.Add("Referer", "https://foo.bar/");
            var response = await client.GetAsync("https://foo.bar/library/5.jpg");

            byte[] image = await response.Content.ReadAsByteArrayAsync();
            var imageSource = ImageSource.FromStream(() => new MemoryStream(image));
            this.Images.Add(imageSource);
        }
    }

When I do this the Image within the StackLayout is empty. I know I can instead just bind to a URL and the ImageSource can download it for me but I'm required to pass a Referrer Header. I can't see anyway for me to force the XAML Image view to allow custom headers, nor can I see a way to do it if I instantiate an instance of ImageSource in my code behind.

When I read the documentation on ImageSource it sounds like it only supports URI, File, Stream and App Resources to load images from. Since I had an array of bytes I wrapped it in a MemoryStream and called ImageSource.FromStream. Nothing loads when the app runs though - the ImageCell is empty.

I know the image was downloaded. I converted the byte[] to a Base64 string then dropped it into Base64 to Image Decoder. The image loads no problem so I know it's being downloaded properly. What I don't understand is why I can't get the image to render on a ImageSource.

I've also tried to just use a normal Image control and have the same problem.

    <ScrollView>
        <ContentView>
            <StackLayout BindableLayout.ItemsSource="{Binding Images}" Orientation="Horizontal">
                <BindableLayout.ItemTemplate>
                    <DataTemplate>
                        <Image Source="{Binding}"></Image>
                    </DataTemplate>
                </BindableLayout.ItemTemplate>
            </StackLayout>
        </ContentView>
    </ScrollView>

Am I doing something completely wrong here or is dynamic downloading of images from the internet with special Headers something I can't do in Xamarin.Forms?


Solution

  • Try to add this.BindingContext = this; in page constructor.

       public MainPage()
       {
            InitializeComponent();
    
            this.BindingContext = this;
       }